[关闭]
@Chilling 2017-02-16T17:58:19.000000Z 字数 2128 阅读 892

HDU-1394: Minimum Inversion Number(逆序数)

线段树


Problem Description

The inversion number of a given number sequence is the number of pairs that satisfy i < j and .

For a given sequence of numbers , if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:

(where m = 0 - the initial seqence)
(where m = 1)
(where m = 2)
...
(where m = n-1)

You are asked to write a program to find the minimum inversion number out of the above sequences.

Input

The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.

Output

For each case, output the minimum inversion number on a single line.

Sample Input

10
1 3 6 9 0 8 5 7 4 2

Sample Output

16

题意:输入n个数,然后按照题目要求交换这n个数的位置,求最小的逆序数是多少。
交换的法则,m从0到n-1变化,每次将第一个数拿到最后,如下:



...

求在这n个序列中逆序数最小是多少。

分析:先用线段树求出最初的逆序数,(也可以归并求出),再循环n-1次,逆序数有这么一个规律:
原来的逆序数是ans,把a[0]移到最后之后,减少逆序数a[0],同时增加逆序数n-a[0]-1个,总的变化ans-a[0]+n-a[0]-1。
因此每次的逆序数ans=ans-a[i]+n-a[i]-1,求出最小的即可。


  1. #include<stdio.h>
  2. #include<algorithm>
  3. #define maxn 5005
  4. using namespace std;
  5. int a[maxn];
  6. struct node
  7. {
  8. int l,r,sum;
  9. }s[4*maxn];
  10. void build(int id,int l,int r)
  11. {
  12. s[id].l=l;
  13. s[id].r=r;
  14. if(l==r)
  15. s[id].sum=0;
  16. else
  17. {
  18. int mid=(l+r)/2;
  19. build(id*2,l,mid);
  20. build(id*2+1,mid+1,r);
  21. s[id].sum=0;
  22. }
  23. }
  24. void rep(int id,int x,int y)//y=1
  25. {
  26. if(s[id].l==s[id].r)
  27. s[id].sum=y;
  28. else
  29. {
  30. int mid=(s[id].l+s[id].r)/2;
  31. if(x<=mid)
  32. rep(id*2,x,y);
  33. else
  34. rep(id*2+1,x,y);
  35. s[id].sum=s[id*2].sum+s[id*2+1].sum;
  36. }
  37. }
  38. int sum(int id,int l,int r)
  39. {
  40. if(l<=s[id].l&&s[id].r<=r)
  41. return s[id].sum;
  42. else
  43. {
  44. int mid=(s[id].l+s[id].r)/2;
  45. if(r<=mid)
  46. return sum(id*2,l,r);
  47. else if(l>mid)
  48. return sum(id*2+1,l,r);
  49. else
  50. return sum(id*2,l,r)+sum(id*2+1,l,r);
  51. }
  52. }
  53. int main()
  54. {
  55. int n,ss,ans;
  56. while(scanf("%d",&n)!=EOF)
  57. {
  58. ss=0;
  59. build(1,0,n-1);
  60. for(int i=0;i<n;i++)
  61. {
  62. scanf("%d",&a[i]);
  63. ss+=sum(1,a[i],n-1);
  64. rep(1,a[i],1);
  65. }
  66. ans=ss;//初始的逆序数
  67. // printf("%d\n",ans);
  68. for(int i=0;i<n;i++)
  69. {
  70. ans=min(ans,ss-a[i]+n-a[i]-1);
  71. ss=ss-a[i]+n-a[i]-1;
  72. }
  73. printf("%d\n",ans);
  74. }
  75. return 0;
  76. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注