标签:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 16188 Accepted Submission(s):
9845
复制了大神的博客:
弄了半天才弄懂题目的意思,就是求最小的逆序数,在此贴下逆序数的概念
题目的意思就好比给出一个序列
如:0 3 4 1 2
设逆序数初始n = 0;
由于0后面没有比它小的,n = 0
3后面有1,2 n = 2
4后面有1,2,n = 2+2 = 4;
所以该序列逆序数为 4
其根据题意移动产生的序列有
3 4 1 2 0 逆序数:8
4 1 2 0 3 逆序数:6
1 2 0 3 4 逆序数:2
2 0 3 4 1 逆序数:4
所以最小逆序数为2
如果是0到n的排列,那么如果把第一个数放到最后,对于这个数列,逆序数是减少a[i],而增加n-1-a[i]的。然后就解决了。
附上代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define M 5005 5 using namespace std; 6 7 struct node 8 { 9 int l,r,n; 10 } ss[M*3]; 11 int n; 12 13 void build(int l,int r,int k) 14 { 15 ss[k].l=l; 16 ss[k].r=r; 17 ss[k].n=0; 18 if(l==r) return; 19 int mid=(ss[k].l+ss[k].r)/2; 20 build(l,mid,k*2); 21 build(mid+1,r,k*2+1); 22 } 23 24 void insert(int x,int k) 25 { 26 if(ss[k].l==x&&ss[k].r==x) 27 { 28 ss[k].n=1; 29 return; 30 } 31 int mid=(ss[k].l+ss[k].r)/2; 32 if(x<=mid) insert(x,k*2); 33 else insert(x,k*2+1); 34 ss[k].n=ss[k*2].n+ss[k*2+1].n; 35 } 36 37 int search(int x,int k) 38 { 39 if(ss[k].l>=x&&ss[k].r<n) return ss[k].n; 40 else 41 { 42 int sum1=0,sum2=0; 43 int mid=(ss[k].l+ss[k].r)/2; 44 if(x<=mid) sum1=search(x,k*2); 45 if(n-1>mid) sum2=search(x,k*2+1); 46 return sum1+sum2; 47 } 48 } 49 50 int main() 51 { 52 int i,j,m; 53 int a[M]; 54 while(~scanf("%d",&n)) 55 { 56 build(0,n-1,1); 57 int sum=0; 58 for(i=0; i<n; i++) 59 { 60 scanf("%d",&a[i]); 61 sum+=search(a[i]+1,1); 62 insert(a[i],1); 63 } 64 int minx=sum; 65 for(i=0; i<n; i++) 66 { 67 sum=sum+n-2*a[i]-1; 68 if(sum<minx) minx=sum; 69 } 70 printf("%d\n",minx); 71 72 } 73 return 0; 74 }
hdu 1394 Minimum Inversion Number
标签:
原文地址:http://www.cnblogs.com/pshw/p/5310427.html