出處:http://blog.csdn.net/enjoying_science/article/details/44114035
(有難度,以后回來填坑)
閱讀代碼中:
1 #include<stdio.h> 2 #include<iostream> 3 using namespace std; 4 #define ForD(i,n) for(int i=n;i;i--) 5 #define F (100000007) 6 #define MAXN (2*200000+10) 7 long long mul(long long a,long long b){return (a*b)%F;} 8 long long add(long long a,long long b){return (a+b)%F;} 9 long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;} 10 11 int n,root=0;/*n->葉子結點數,root->根序號?*/ 12 struct node 13 { 14 int fa; /*父結點的下標*/ 15 int ch[2]; /*0->左樹下標 1->右樹下標*/ 16 int size; /*size->當前結點含有的有效結點數*/ 17 int c; /*當前結點的數值*/ 18 node():size(0),c(0){ch[0]=ch[1]=fa=0;} /*初始化為0*/ 19 }a[MAXN]; /*樹形數組->紀錄各葉結點的數值*/ 20 21 void update(int x)/*更新葉結點個數*/ 22 { 23 a[x].size=a[a[x].ch[0]].size+a[a[x].ch[1]].size+(a[x].c>0); 24 } 25 int tail=0; 26 void pushdown(int x)/*將葉結點的父結點指向當前結點*/ 27 { 28 a[a[x].ch[0]].fa=a[a[x].ch[1]].fa=x; 29 } 30 31 /*創建樹*/ 32 void build(int &x) 33 { 34 if (!x) x=++tail; 35 scanf("%d",&a[x].c); 36 if (a[x].c==0) 37 { 38 build(a[x].ch[0]);/*創建左子樹*/ 39 build(a[x].ch[1]);/*創建右子樹*/ 40 update(x);pushdown(x);/*更新當前結點的有效葉結點個數,以及父結點指向*/ 41 }else a[x].size=1; 42 } 43 44 void rotate(int x)/*旋轉*/ 45 { 46 int y=a[x].fa,z=a[y].fa; 47 bool p=a[y].ch[0]==x; 48 if (z) /*有爺爺*/ 49 { 50 if (a[z].ch[0]==y) /*未旋轉*/ 51 a[z].ch[0]=x;/*將子樹提拔為父樹(升序)*/ 52 else 53 a[z].ch[1]=x; /*還原狀態*/ 54 } 55 a[x].fa=z,a[y].fa=x;/*當前結點與父結點交換(父結點指向)*/ 56 if (a[x].ch[p]) /*原子樹是否有右樹(隔代轉移)*/ 57 a[a[x].ch[p]].fa=y; 58 a[y].ch[p^1]=a[x].ch[p]; 59 a[x].ch[p]=y; /*父樹移至子樹的右端(右樹)*/ 60 update(y); /*更新旋轉后,子樹的結點的有效結點數*/ 61 } 62 63 void splay(int x) 64 { 65 while (a[x].fa)/*不為根結點*/ 66 { 67 int y=a[x].fa,z=a[y].fa; 68 if (z) /*有爺爺*/ 69 if ((a[y].ch[0]==x)^(a[z].ch[0]==y)) rotate(x);/*旋轉*/ 70 else rotate(y); 71 rotate(x); 72 } 73 update(x); 74 } 75 void ins(long long &tot,int x,int y) 76 { 77 a[x].size++; /*插入+1*/ 78 if (a[y].c<=a[x].c) /*是逆序對*/ 79 { 80 if (a[x].ch[0]) /*左樹有子*/ 81 ins(tot,a[x].ch[0],y); 82 else /*左樹無子*/ 83 a[y].fa=x,splay(a[x].ch[0]=y);/*右數插入到左樹子*/ 84 } 85 else 86 { 87 tot+=a[a[x].ch[0]].size+(a[x].c>0); 88 if (a[x].ch[1]) ins(tot,a[x].ch[1],y); 89 else a[y].fa=x,splay(a[x].ch[1]=y); 90 } 91 } 92 93 94 int q[MAXN],size; 95 96 void clac(int x,int y) 97 { 98 if (a[y].ch[0]) clac(x,a[y].ch[0]); 99 if (a[y].c) q[++size]=y; 100 if (a[y].ch[1]) clac(x,a[y].ch[1]); 101 } 102 103 long long merge(bool &lor,int z)/*分治*/ 104 { 105 int x=a[z].ch[0],y=a[z].ch[1]; 106 if (a[x].size<a[y].size) /*判斷葉結點多的往前調(平衡樹?)*/ 107 swap(x,y); 108 109 a[x].fa=0;a[y].fa=0;q[1]=y; 110 size=0;clac(x,y); 111 long long tot=0; /*最少逆序對*/ 112 ForD(i,size) /*循環(子結點數)次*/ 113 { 114 int now=q[i]; 115 a[now].ch[0]=a[now].ch[1]=a[now].fa=0; 116 a[now].size=1; 117 ins(tot,x,now); 118 x=now; 119 } 120 a[x].fa=z; 121 a[z].ch[0]=0,a[z].ch[1]=x; 122 return tot; 123 } 124 125 126 long long qur(int &x) 127 { 128 if (a[x].c) return 0;/*若根結點沒有葉結點,則逆序對為0*/ 129 else 130 { 131 long long lson=a[a[x].ch[0]].size,rson=a[a[x].ch[1]].size,ls=qur(a[x].ch[0]),rs=qur(a[x].ch[1]); 132 bool lor=0; 133 long long ms=merge(lor,x); 134 return ls+rs+min(lson*rson-ms,ms); 135 } 136 } 137 int main() 138 { 139 scanf("%d",&n); 140 build(root); 141 cout<<qur(root)<<endl; 142 return 0; 143 }