Minimum Inversion Number

hdu1394:http://acm.hdu.edu.cn/showproblem.php?pid=1394

题意描述:给你一个有0--n-1数字组成的序列,然后进行这样的操作,每次将最前面一个元素放到最后面去会得到一个序列,那么这样就形成了n个序列,那么每个序列都有一个逆数,找出其中最小的一个输出!

题解:求最小逆序数的时候有个巧妙的想法,当把x放入数组的后面,此时的逆序数应该为x没放入最后面之前的逆序总数加上(n-x)再减去(x-1);sum = sum+(n-x[i])-(x[i]-1)。

求逆序数:此题方法1:暴收

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 int map[5002];
 7 int n,counts;
 8 int main(){
 9     while(~scanf("%d",&n)){
10         counts=0;
11     for(int i=1;i<=n;i++)
12           scanf("%d",&map[i]);
13     for(int i=1;i<=n;i++)
14        for(int j=1;j<i;j++)
15            if(map[j]>map[i])
16              counts++;
17          int ans=counts;
18     for(int i=1;i<n;i++){
19              counts=counts+n-2*map[i]-1;
20              if(counts<ans)
21                ans=counts;
22          }
23         printf("%d\n",ans);      
24     }
25 }
View Code

方法二:线段树.

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 int n,map[5002];
 7 struct Node{
 8     int left;
 9     int right;
10     int sum;
11 }node[5002*4];
12 void build(int l,int r,int idx){
13     node[idx].left=l;
14     node[idx].right=r;
15     node[idx].sum=0;
16     if(l==r)return;
17     int mid=(l+r)/2;
18     build(l,mid,idx<<1);
19     build(mid+1,r,idx<<1|1);
20 }
21 void update(int pos,int idx){
22     if(node[idx].left==node[idx].right){
23         node[idx].sum=1;
24         return;
25     }
26   int mid=(node[idx].left+node[idx].right)/2;
27   if(mid>=pos)update(pos,idx<<1);
28   else if(mid<pos)update(pos,idx<<1|1);
29   node[idx].sum=node[idx<<1].sum+node[idx<<1|1].sum;    
30 }
31 int query(int l,int r,int idx){
32     if(node[idx].left==l&&node[idx].right==r)
33         return node[idx].sum;
34     int mid=(node[idx].left+node[idx].right)/2;
35     if(mid>=r)return query(l,r,idx<<1);
36     else if(mid<l)return query(l,r,idx<<1|1);
37     else   return query(l,mid,idx<<1)+query(mid+1,r,idx<<1|1);
38 }
39 int main(){
40     int counts;
41     while(~scanf("%d",&n)){
42         counts=0;
43         build(1,n,1);
44         for(int i=1;i<=n;i++){
45             scanf("%d",&map[i]);
46             if(map[i]+2<=n)
47             counts+=query(map[i]+2,n,1);
48             update(map[i]+1,1);
49         }
50         int ans=counts;
51          for(int i=1;i<n;i++){
52              counts=counts+n-2*map[i]-1;
53              if(counts<ans)ans=counts;
54          }
55          printf("%d\n",ans);      
56     }
57 }
View Code

 

posted on 2013-11-17 15:22  天依蓝  阅读(118)  评论(0编辑  收藏  举报

导航