poj 2299
思路:
1、将原序列seq[]的下标按照seq[]的值升序排序存入res[]中。
2、假如我们知道res[j]的后面小于res[j]的数的个数x的话,那么res[j]需要交换的次数为j-res[j]+x;(自己推一下就知道)。
3、如何求x呢?我们可以用树状数组sum[]来统计res[]从后往前处理过的数。
4、求和累加 j-res[j]+x; (j从n-1到0)
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define MAX 500010 int seq[MAX],res[MAX]; __int64 sum[MAX]; bool com(int a,int b) { return seq[a]<seq[b]; } int lowbit(int i) { return i & (-i); } int GetSum(int i) { int s=0; while(i>0) { s+=sum[i]; i-=lowbit(i); } return s; } int update(int i,int n) { while(i<n) { sum[i]++; i+=lowbit(i); } return 0; } int main() { int i,n; __int64 r; while(scanf("%d",&n) && n) { memset(sum,0,sizeof(sum)); for(i=0;i<n;i++) { scanf("%d",&seq[i]); res[i]=i; } sort(res,res+n,com); r=0; for(i=n-1;i>=0;i--) { __int64 g=GetSum(res[i]); r+=i-res[i]+g; update(res[i]+1,n); } printf("%I64d\n",r); } return 0; }