hdu 1394 Minimum Inversion Number(线段树)

参考:http://blog.sina.com.cn/s/blog_691ce2b70101ldmm.html

https://blog.csdn.net/wiking__acm/article/details/7920429

语法:https://zhidao.baidu.com/question/172532047.html

 1 #include <stdio.h>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 int a[5005];
 7 struct Node{
 8     int l,r,num;//num该区间已出现数的个数
 9 }tree[50000];
10 
11 void Build(int n,int x,int y){
12     tree[n].l = x;
13     tree[n].r = y;
14     tree[n].num = 0;
15     if(x == y){
16         return;
17     }
18     int mid = (x + y) / 2;
19     Build(2*n,x,mid);
20     Build(2*n+1,mid+1,y);
21 }
22 
23 void Modify(int n,int x){//在输入的相应叶节点加1
24     int l = tree[n].l;
25     int r = tree[n].r;
26     int mid = (l + r) / 2;
27     if(x == l && x == r){
28         tree[n].num = 1;
29         return;
30     }
31     if(x <= mid)    Modify(2*n,x);
32     else            Modify(2*n+1,x);
33     tree[n].num = tree[2*n].num + tree[2*n+1].num;
34 }
35 
36 int Query(int n,int x,int y){//求大于该数且已经出现的数个数,n节点序号,x左端点,y右端点
37     int l = tree[n].l;
38     int r = tree[n].r;
39     int mid = (l + r) / 2;
40     int ans = 0;
41     if(x == l && y == r)
42         return tree[n].num;
43     if(x <= mid)   ans += Query(2*n,x,min(mid,y));
44     if(y > mid)    ans += Query(2*n+1,max(mid+1,x),y);
45     return ans;
46 }
47 int main(){
48     int n,sum,ans;
49     int i,j;
50 
51     while(scanf("%d",&n) != EOF){
52         sum = 0;
53         Build(1,0,n-1);//区间端点取0~n-1即可
54         for(i = 1;i <= n;i++){
55             scanf("%d",&a[i]);
56             Modify(1,a[i]);
57             sum += Query(1,a[i]+1,n-1);
58         }
59         ans = sum;
60         for(i = 1;i < n;i++){
61             sum = sum + (n - 1 - a[i]) - a[i];//根据递推式加上接下来依次循环的序列的逆序数
62             if(sum < ans)
63                 ans = sum;//要最小的
64         }
65         printf("%d\n",ans);
66     }
67 }

 

posted @ 2018-08-22 10:42  hemeiwolong  阅读(118)  评论(0编辑  收藏  举报