标签:
3 2 3 1
7HintInput Details Three cows are standing in line with respective grumpiness levels 2, 3, and 1. Output Details 2 3 1 : Initial order. 2 1 3 : After interchanging cows with grumpiness 3 and 1 (time=1+3=4). 1 2 3 : After interchanging cows with grumpiness 1 and 2 (time=2+1=3).
题意:给出一组数从1到N打乱,要求把数组又一次有序(从小到大),仅仅能交换相邻的两个数字。代价为相邻两个数字和。求最小代价?
思路:对于每一个数字x,我们仅仅须要把它和前面比它大的数字交换。求出交换代价,反复运行就能得出答案。
这个代价就是,比它大的数字个数t*x+前面比它大的数字和。
<pre name="code" class="cpp">#include<stdio.h> #include<math.h> #include<string.h> #include<stdlib.h> #include<algorithm> #include<vector> #include<functional> #include<iostream> using namespace std; #define N 100005 #define ll __int64 int a[N],cnt[N],n; //记录数字个数 ll sum[N]; //记录数字和 int lowbit(int x) { return x&(-x); } void add(int x) { int d=x; while(x<=n) { cnt[x]++; sum[x]+=d; x+=lowbit(x); } } int sum1(int x) //求比x小的数字已经出现几个(包含x) { int s=0; while(x) { s+=cnt[x]; x-=lowbit(x); } return s; } ll sum2(int x) //求当前出现的比x大的数字和 { ll s=0; while(x) { s+=sum[x]; x-=lowbit(x); } return s; } int main() { int i,k,t; while(scanf("%d",&n)!=-1) { memset(cnt,0,sizeof(cnt)); memset(sum,0,sizeof(sum)); ll ans=0; for(i=1;i<=n;i++) { scanf("%d",&a[i]); add(a[i]); t=sum1(a[i]); k=i-t; //前面有几个比x大的数 if(k!=0) { ans+=(ll)a[i]*k; //注意数字会超出int ans+=sum2(n)-sum2(a[i]); //求当前位置出现的比x大的数字和 } } printf("%I64d\n",ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/yxwkf/p/5093620.html