HDU-1394-Minimum Inversion Number
HDU-1394-Minimum Inversion Number
http://acm.hdu.edu.cn/showproblem.php?pid=1394
题意是给出n个数,求其逆序数,并每次将第一个数移至最后,再求其逆序数,求这n个排列中逆序数最小的一个
逆序数的简单定义:The inversion number of a givennumber sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i< j and ai > aj.
假设已求得一个排列的逆序数为sum,并且数组为a[n],现把第一个数移至末尾,因为0至n-1个数连续,比a[0]大的数将变成逆序,比a[0]小的数将不构成逆序,所以现在的逆序数为sum+=(比a[0]大的数—比a[0]小的数)
即sum+=(n-1-a[0]-a[0]) 即sum+=(n-1-2*a[0])
此时求原始排列的逆序数可用暴力的方法,即每个数都和前面的数比较
#include<stdio.h> #include<string.h> #include<stdlib.h> int main() { int n,sum,i,j,ans; int a[5005]; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) scanf("%d",&a[i]); sum=0; for(i=0;i<n;i++) for(j=0;j<i;j++) if(a[j]>a[i]) sum++; ans=sum; for(i=0;i<n;i++) { sum+=(n-1-2*a[i]); if(sum<ans) ans=sum; } printf("%d\n",ans); } return 0; }
暴力的方法在求原始排列的逆序数时比较耗时,此题也可用线段树来做
1 3 6 9 0 8 5 7 4 2
依次插入,插入1时,(1,n-1]中出现的有v1=0
插入3时,(3,n-1]中出现的有v2=0
...
插入0时,(0,n-1]中出现的有v5=4
...
将v1至v10叠加即可
#include<stdio.h> #include<string.h> #include<stdlib.h> #define N 5005 int a[N]; struct cam { int x; //起点 int y; //终点 int val; }list[N*4]; void build(int k,int x,int y) //建树 { int mid; list[k].x=x; list[k].y=y; list[k].val=0; if(list[k].x==list[k].y) return; mid=(x+y)/2; build(k<<1,x,mid); build(k<<1|1,mid+1,y); } int find(int k,int x,int y) //(x,y]中比x大且出现的数 { int mid; if(list[k].x==x&&list[k].y==y) return list[k].val; mid=(list[k].x+list[k].y)/2; if(x>mid) return find(k<<1|1,x,y); else if(y<=mid) return find(k<<1,x,y); else return find(k<<1,x,mid)+find(k<<1|1,mid+1,y); } void update(int x,int k) //更新所有包含x的区间的val值 { int mid; list[k].val++; if(list[k].x==list[k].y) return; mid=(list[k].x+list[k].y)/2; if(x<=mid) update(x,k<<1); else update(x,k<<1|1); } int main() { int i,n,sum,ans; while(scanf("%d",&n)!=EOF) { build(1,0,n-1); sum=0; for(i=0;i<n;i++) { scanf("%d",&a[i]); sum+=find(1,a[i],n-1); update(a[i],1); } ans=sum; for(i=0;i<n;i++) { sum+=(n-1-2*a[i]); if(sum<ans) ans=sum; } printf("%d\n",ans); } return 0; }
posted on 2012-07-21 10:05 java课程设计例子 阅读(161) 评论(0) 编辑 收藏 举报