出处: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 }