-
Notifications
You must be signed in to change notification settings - Fork 0
/
SBT.cpp
119 lines (113 loc) · 2.72 KB
/
SBT.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 200005
int n,m;
long long ans;
//SBT,Size Blance Tree
//S是size,Left和Right是左右节点
int S[MAXN],Left[MAXN],Right[MAXN];
unsigned int Key[MAXN];
int Left_Rotate(int rt){
int k=Right[rt];
Right[rt]=Left[k];
Left[k]=rt;
S[k]=S[rt];
S[rt]=S[Left[rt]]+S[Right[rt]]+1;
return rt=k;
}
int Right_Rotate(int rt){
int k=Left[rt];
Left[rt]=Right[k];
Right[k]=rt;
S[k]=S[rt];
S[rt]=S[Left[rt]]+S[Right[rt]]+1;
return rt=k;
}
int Maintain(int rt,bool flag){
//检查平衡性,不符合的进行左右旋转,并更换rt
if(flag){
if(S[Left[Right[rt]]]>S[Left[rt]] || S[Right[Right[rt]]]>S[Left[rt]]){
if(S[Left[Right[rt]]]>S[Left[rt]])Right[rt]=Right_Rotate(Right[rt]);
return Left_Rotate(rt);
}
}
else{
if(S[Right[Left[rt]]]>S[Right[rt]] || S[Left[Left[rt]]]>S[Right[rt]]){
if(S[Right[Left[rt]]]>S[Right[rt]])Left[rt]=Left_Rotate(Left[rt]);
return Right_Rotate(rt);
}
}
return rt;
}
int Insert(int rt,int RT){
S[rt]+=1;
//先插入后调整平衡性
//RR和LR是左旋,其他是右旋
if(Key[RT]>Key[rt]){
if(Right[rt]>0)Right[rt]=Insert(Right[rt],RT);
else{
Right[rt]=RT;
}
}
else{
if(Left[rt]>0)Left[rt]=Insert(Left[rt],RT);
else{
Left[rt]=RT;
}
}
return rt=Maintain(rt,Key[RT]>Key[rt]);
}
int Rank(int rt,int v){
/*
*param:rt是一个已经完成了的SBT,v则是要比较的值
*本函数比较v与二叉树根节点的值来获的SBT上比v小的节点有多少个
*/
if(v>Key[rt]){
if(Right[rt]==0)return S[rt];
return S[rt]-S[Right[rt]]+Rank(Right[rt],v);
}
if(Left[rt]==0)return 0;
return Rank(Left[rt],v);
}
int Merge(int rt,int Start,int End){
long long lans=0,rans=0;
for(int i=Start;i<=End;i++){
lans+=Rank(rt,Key[i]); //比key[i]小的节点有多少个
rans+=S[rt]-Rank(rt,Key[i]+1); //比key[i]大的节点有多少个
}
for(int i=Start;i<=End;i++){
//将每个节点插入平衡二叉树
S[i]=1;
Left[i]=Right[i]=0;
rt=Insert(rt,i);
}
ans+=min(lans,rans);//最小的则是逆序对数
return rt;
}
int Init(){
int v;
scanf("%d",&v);
if(v){
Key[++m]=v;
S[m]=1;
Left[m]=Right[m]=0;
return m;
}
int TL,TR,Ls,Le,Rs,Re;
Ls=m+1;
TL=Init();
Le=m;
Rs=m+1;
TR=Init();
Re=m;
if(S[TL]<S[TR])return Merge(TR,Ls,Le);
return Merge(TL,Rs,Re);
}
int main()
{
scanf("%d",&n);
Init();
printf("%I64d\n",ans);
return 0;
}