1、http://poj.org/problem?id=2299
2、题目大意:
一个序列有n个数字,他们是无序的,现在要将这些数字交换顺序,使得他们是从小到大排列的,输出最少交换几次,3、思路分析
如果数字个数很小的话,实际上是可以用冒泡排序的,冒泡交换的步数实际上就是所求,但是数据很大,所以不能这么做,看网上解题报告用树状数组解决,作为第一个树状数组的题目,真心觉得好难,还得继续看,
还有一个问题就是除了n非常大不能用冒泡做,还有就是这n个数字也是非常大的,所以要用到离散化
4、题目
Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 37365 | Accepted: 13438 |
Description
Input
Output
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0
Source
5、AC代码:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define N 500005 int b[N],n,c[N]; struct node { int id; int x; } a[N]; int cmp(node a,node b) { return a.x<b.x; } void update(int i,int x) { while(i<=n) { c[i]+=x; i+=i&(-i); } } int sum(int i) { int tmp=0; while(i>0) { tmp+=c[i]; i-=i&(-i); } return tmp; } int main() { while(scanf("%d",&n)!=EOF) { if(n==0) break; memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); for(int i=1; i<=n; i++) { scanf("%d",&a[i].x); a[i].id=i; } sort(a+1,a+n+1,cmp); //离散化 a[0].x=-1; for(int i=1; i<=n; i++) { if(a[i].x!=a[i-1].x) b[a[i].id]=i; else b[a[i].id]=b[a[i-1].id]; } long long ans=0; for(int i=1; i<=n; i++) { //每次更新后判断左边比当前数大的数的个数 update(b[i],1); ans+=sum(n)-sum(b[i]); } printf("%lld\n",ans); } return 0; }