HDU 3743 Frosh Week(树状数组或归并排序求逆序)
http://acm.hdu.edu.cn/showproblem.php?pid=3743
题意:
给你一个n排列,每次你只能交换相邻的两个整数,现在要你用最少的交换次数使得该排列呈递增排列。要你输出需要交换的次数。
分析:
首先这题类似于POJ2299:
http://blog.csdn.net/u013480600/article/details/21277047
其实题目就是给你n个数的排列,然后问你这n个数的逆序和是多少.可以用归并排序做,也可以用树状数组左,其中用树状数组做的话,每读入一个a[i],当前树状数组中先查找已经出现的比a[i]大的数有多少,即执行temp=sum(n)-sum(a[i]),然后这个temp就是a[i]的逆序,执行ans+=temp;然后在标记a[i]值已经出现过一次了,执行add(a[i],1)即可.
如果用归并排序做的话,参考刘汝佳的书.
AC代码:125ms归并排序
<span style="font-size:18px;">#include<cstdio> using namespace std; const int MAXN=500000+100; int a[MAXN],b[MAXN]; long long merge_sort(int *a,int *b,int i,int j)//归并排序并返回逆序值,a为待排序的数组,b为辅助空间 { if(i==j)return 0; long long ans=0;//逆序值 int mid= (i+j)/2; ans+=merge_sort(a,b,i,mid);//获取左边的逆序值 ans+=merge_sort(a,b,mid+1,j);//获取右边的逆序值 int p=i,q=mid+1,k=i; while(p<=mid||q<=j)//获取左边与右边关联的逆序值 { if(p>mid || (q<=j&&a[p]>a[q])) { b[k++]=a[q++]; ans+=mid-p+1; } else { b[k++]=a[p++]; } } for(int k=i;k<=j;k++)a[k]=b[k]; return ans; } int main() { long long ans; int n; while(scanf("%d",&n)==1&&n) { for(int i=0;i<n;i++) { scanf("%d",&a[i]); } ans = merge_sort(a,b,0,n-1); printf("%I64d\n",ans); } return 0; } </span>
AC代码:140ms,树状数组+离散化数据
<span style="font-size:18px;">#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN=1000000+10; int c[MAXN]; int lowbit(int x) { return x&(-x); } int sum(int x) { int res=0; while(x) { res +=c[x]; x-=lowbit(x); } return res; } void add(int x,int v) { while(x<MAXN) { c[x]+=v; x+=lowbit(x); } } struct node { int v; int index; bool operator <(const node &b)const { return v<b.v; } }nodes[MAXN]; int a[MAXN]; int main() { int n; while(scanf("%d",&n)==1&&n) { for(int i=1;i<=n;i++) { scanf("%d",&nodes[i].v); nodes[i].index=i; } sort(nodes+1,nodes+n+1); int max_num=1; a[nodes[1].index]=1; for(int i=2;i<=n;i++) { if(nodes[i].v==nodes[i-1].v) a[nodes[i].index]=a[nodes[i-1].index]; else a[nodes[i].index]=++max_num; } long long ans=0; memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { int x=a[i]; add(x,1); ans+= sum(n)-sum(x); } printf("%I64d\n",ans); } return 0; }</span>