码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 1394 树状数组(逆序数)

时间:2014-07-22 08:07:36      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   java   color   os   

Minimum Inversion Number

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10100    Accepted Submission(s): 6192


Problem Description
The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.

For a given sequence of numbers a1, a2, ..., an, 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:

a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (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的序列a1,a2....an-1,an。该序列逆序数为num0.

然后把序列首位元素a1弄到最后面得:

a2,a3....an-1,an,a1    此时逆序数为num1。

在把序列首位元素a2弄到最后面的:

a3,a4...an,a1,a2    此时逆序数num2.

。。。

不断的进行上面操作,每次得一个逆序数,求这些逆序数中最小的为多少。

 

逆序数可以由线段树、树状数组、归并排序求出,在这就不详细讲了,不懂的朋友可以百度。

非要按照上面操作模拟然后在找出最小的吗?no,这样的话一定会超时,下面说一个简单的分析思路:

设咱们第一次求出的逆序数为num0,第二次求出的逆序数为num1...依次类推,只需找出n-1次的逆序数就行了,以后就重复了,第一次逆序数用上面三种方法可求得(最好不要用归并排序,本题中咱们需要保存原序列,归并排序会打乱原序列,这样的话还要开一个辅助数组),num0就求出来了,观察上述操作,a1放到最后面的话,因为a1之前为首位,后面比a1大的即之前没和a1构成逆序数的数此时和a1构成了逆序数(设这些比a1大的数的数目为s1,比a1小的数的数目为s2),那么num0+1,而后面比a1小的即之前和a1构成逆序数的数此时不能和a1构成逆序数了,num0-s2,所以num1=num0+s1-s2。

然后a2位于首位,重复上述操作得num2。

。。。

这样下来num0----num(n-1)都求出来了,找其中最小的即为答案。

 

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 using namespace std;
 6 #define N 5005
 7 #define inf 999999999
 8 
 9 int c[N];
10 int a[N];
11 
12 int lowbit(int x){
13     return x&(-x);
14 }
15 
16 void update(int x){
17     while(x<N){
18         c[x]++;
19         x+=lowbit(x);
20     }
21 }
22 
23 int get_sum(int x){
24     int ans=0;
25     while(x>0){
26         ans+=c[x];
27         x-=lowbit(x);
28     }
29     return ans;
30 }
31 
32 main()
33 {
34     int n, i, j, k;
35     while(scanf("%d",&n)==1){
36         memset(c,0,sizeof(c));
37         int num=0;
38         for(i=1;i<=n;i++){
39             scanf("%d",&a[i]);
40             a[i]++;
41             num+=get_sum(N-1)-get_sum(a[i]);  
42             update(a[i]);               
43         }                                  //以上用树状数组求序列a的逆序数 
44         int minh=inf;
45         for(i=1;i<=n;i++)
46         {
47             num=num-(a[i]-1)+(n-a[i]);       //每次由之前的逆序数推出此时的逆序数 
48             minh=min(minh,num);             //更新最小值 
49         }
50         printf("%d\n",minh);
51     }
52 }

 

HDU 1394 树状数组(逆序数),布布扣,bubuko.com

HDU 1394 树状数组(逆序数)

标签:des   style   blog   java   color   os   

原文地址:http://www.cnblogs.com/qq1012662902/p/3857561.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!