HDU 1394.Minimum Inversion Number-最小逆序数-完全版线段树(单点增减、区间求和)

 

HDU1394.Minimum Inversion Number

 

这个题求最小逆序数,先建一个空的树,然后每输入一个值,就先查询一下,查询之后,更新线段树,然后遍历一遍,每次将第一个数放到最后之后,减少的逆序数为x[i],增加的为n-x[i]-1;

所以该种序列的逆序数为sum+=n-x[i]-x[i]-1。直接遍历的时候找最小值就可以了。

写的脑子有点乱。。。

 

代码:

  1 //c
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<cstdlib>
  8 #include<queue>
  9 #include<stack>
 10 using namespace std;
 11 typedef long long ll;
 12 const int inf=0x3f3f3f3f;
 13 const double eps=1e-5;
 14 const int maxn=5*1e5+10;
 15 #define lson l,m,rt<<1
 16 #define rson m+1,r,rt<<1|1
 17 int sum[maxn<<2],MAX[maxn<<2];
 18 
 19 void PushUp(int rt){
 20     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 21     //MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]);
 22 }
 23 /*
 24 void build(int l,int r,int rt){
 25     if(l==r){
 26         scanf("%d",&sum[rt]);
 27         //scanf("%d",&MAX[rt]);
 28         return ;
 29     }
 30     int m=(l+r)>>1;
 31     build(lson);
 32     build(rson);
 33     PushUp(rt);
 34 }
 35 */
 36 void build(int l,int r,int rt){
 37     sum[rt]=0;
 38     if(l==r)return ;
 39     int m=(l+r)>>1;
 40     build(lson);
 41     build(rson);
 42 }
 43 void update(int p,int l,int r,int rt){
 44     if(l==r){
 45         sum[rt]++;
 46         return ;
 47     }
 48     int m=(l+r)>>1;
 49     if(p<=m)update(p,lson);
 50     else update(p,rson);
 51     PushUp(rt);
 52 }
 53 /*
 54 //单点增减
 55 void update(int p,int add,int l,int r,int rt){
 56     if(l==r){
 57         sum[rt]+=add;
 58         return ;
 59     }
 60     int m=(l+r)>>1;
 61     if(p<=m)update(p,add,lson);
 62     else update(p,add,rson);
 63     PushUp(rt);
 64 }
 65 */
 66 /*
 67 //单点更新
 68 void update(int p,int sc,int l,int r,int rt){
 69     if(l==r){
 70         MAX[rt]=sc;
 71         return ;
 72     }
 73     int m=(l+r)>>1;
 74     if(p<=m)update(p,sc,lson);
 75     else update(p,sc,rson);
 76     PushUp(rt);
 77 }
 78 */
 79 
 80 //区间求和
 81 int query(int L,int R,int l,int r,int rt){
 82     if(L<=l&&r<=R){
 83         return sum[rt];
 84     }
 85     int m=(l+r)>>1;
 86     int ret=0;
 87     if(L<=m)ret+=query(L,R,lson);
 88     if(R>m) ret+=query(L,R,rson);
 89     return ret;
 90 }
 91 
 92 /*
 93 //区间最值
 94 int query(int L,int R,int l,int r,int rt){
 95     if(L<=l&&r<=R){
 96         return MAX[rt];
 97     }
 98     int m=(l+r)>>1;
 99     int ret=0;
100     if(L<=m)ret=max(ret,query(L,R,lson));
101     if(R>m) ret=max(ret,query(L,R,rson));
102     return ret;
103 }
104 */
105 int x[maxn];
106 int main(){
107     int n;
108     while(~scanf("%d",&n)){
109         build(0,n-1,1);
110         int sum=0;
111         for(int i=0;i<n;i++){
112             scanf("%d",&x[i]);
113             sum+=query(x[i],n-1,0,n-1,1);
114             update(x[i],0,n-1,1);
115         }
116         int ret=sum;
117         for(int i=0;i<n;i++){
118             sum+=n-x[i]-x[i]-1;
119             ret=min(ret,sum);
120         }
121         printf("%d\n",ret);
122     }
123     return 0;
124 }

 

posted @ 2018-07-11 13:54  ZERO-  阅读(161)  评论(0编辑  收藏  举报