Nhảy chuyển đến

Toàn cục cân bằng nhị xoa thụ

Dẫn vào

Trước trí tri thức:Thụ liên mổ phân

Bởi vì thụ liên mổ phân thời gian phức tạp độ vì,Mà chúng ta biết rõ LCT tuy rằng thời gian phức tạp độ vì,Nhưng hằng số trọng đại, khả năng so thụ liên mổ phân còn chậm. Như vậy có cái gì đã là,Hằng số lại tương đối nhỏ lại phương pháp đâu? Lúc này toàn cục cân bằng nhị xoa thụ liền xuất hiện.

Toàn cục cân bằng nhị xoa thụ trên thực tế là một viên nhị xoa thụ rừng rậm, trong đó mỗi viên nhị xoa thụ giữ gìn một cái trọng liên. Nhưng là cái này rừng rậm nhị xoa thụ lại lẫn nhau có liên hệ, trong đó mỗi cái nhị xoa thụ căn liền hướng cái này trọng liên liên đầu phụ thân, tựa như LCT trung giống nhau. Nhưng toàn cục cân bằng nhị xoa thụ là trạng thái tĩnh thụ, khác nhau với LCT, kiến thành sau thụ hình thái bất biến.

Toàn cục cân bằng nhị xoa thụ là một loại có thể xử lý trên cây liên sửa chữa / tuần tra số liệu kết cấu, có thể làm được:

  • Một cái liên chỉnh thể sửa chữa.
  • Một cái liên chỉnh thể tuần tra.
  • Cầu gần nhất công cộng tổ tiên, tử thụ sửa chữa, tử thụ tuần tra chờ, này đó phức tạp độ cùng trọng liên mổ phân là giống nhau.

Chủ yếu tính chất

  1. Toàn cục cân bằng nhị xoa thụ từ rất nhiều cây nhị xoa thụ thông qua nhẹ biên liền lên tạo thành, mỗi một cây nhị xoa thụ giữ gìn nguyên thụ một cái trọng liên, trong đó tự biến lịch trình tự chính là này trọng liên chiều sâu đơn điệu tăng lên trình tự. Mỗi cái tiết điểm đều chỉ xuất hiện ở một cây nhị xoa thụ trung.
  2. Biên chia làm trọng biên cùng nhẹ biên, trọng biên là bao hàm ở nhị xoa thụ trung biên, giữ gìn thời điểm tựa như bình thường giữ gìn nhị xoa thụ giống nhau, ký lục tả hữu nhi tử cùng phụ tiết điểm. Nhẹ biên từ một viên nhị xoa thụ căn tiết điểm chỉ hướng nó sở đối ứng trọng liên đỉnh tiết điểm phụ tiết điểm. Nhẹ biên giữ gìn thời điểm "Nhận phụ không nhận tử", tức chỉ có thể từ tử tiết điểm phỏng vấn đến phụ tiết điểm, không thể trái lại. Chú ý, toàn cục cân bằng nhị xoa thụ trung biên cùng nguyên thụ trung biên không có đối ứng quan hệ.
  3. Tính thượng trọng biên cùng nhẹ biên, toàn cục cân bằng nhị xoa thụ độ cao làCấp bậc. Này là bảo đảm toàn cục cân bằng nhị xoa thụ thời gian phức tạp độ tính chất.

Phía dưới là một cái toàn cục cân bằng nhị xoa thụ thành tựu ví dụ. Đệ nhất trương đồ là nguyên thụ, lấy tiết điểm 1 làm gốc tiết điểm. Thật tuyến là trọng biên.

global-bst-1

Đệ nhị trương đồ là kiến ra tới toàn cục cân bằng nhị xoa thụ, trong đó hư tuyến là nhẹ biên, thật tuyến là trọng biên, mỗi một cây nhị xoa thụ dùng hồng vòng tỏ vẻ.

global-bst-2

Thành tựu

Đầu tiên là giống bình thường trọng liên mổ phân giống nhau, một lần DFS cầu ra mỗi cái tiết điểm trọng nhi tử. Sau đó từ căn bắt đầu, tìm được căn tiết điểm nơi trọng liên, đối với này đó điểm nhẹ nhi tử đệ quy thành tựu, cũng liền thượng nhẹ biên. Sau đó chúng ta yêu cầu cấp trọng liên thượng điểm kiến một cây nhị xoa thụ. Chúng ta trước đem trọng liên thượng điểm tồn đến số tổ, cầu ra mỗi cái điểm nhẹ nhi tử tử thụ lớn nhỏ chi cùng thêm một ( tức nên điểm bản thân sở cống hiến size ). Sau đó chúng ta dựa theo cái này cầu ra này trọng liên thêm quyền điểm giữa, đem nó làm nhị xoa thụ căn, hai bên đệ quy thành tựu, cũng liền thượng trọng biên.

Số hiệu như sau:

Thực hiện
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
std::vectorint>G[N];
intn,fa[N],son[N],sz[N];

voiddfsS(intu){
sz[u]=1;
for(intv:G[u]){
dfsS(v);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
}

intb[N],bs[N],l[N],r[N],f[N],ss[N];

// cấp b trung [bl,br) nội điểm kiến nhị xoa thụ, phản hồi nhị xoa thụ căn
intcbuild(intbl,intbr){
intx=bl,y=br;
while(y-x>1){
intmid=(x+y)>>1;
if(2*(bs[mid]-bs[bl])bs[br]-bs[bl])
x=mid;
else
y=mid;
}
// nhị phân cầu ra ấn bs thêm quyền điểm giữa
y=b[x];
ss[y]=br-bl;// ss: Nhị xoa thụ trung hạt cơ bản thụ lớn nhỏ
if(blx){
l[y]=cbuild(bl,x);
f[l[y]]=y;
}
if(x+1br){
r[y]=cbuild(x+1,br);
f[r[y]]=y;
}
returny;
}

intbuild(intx){
inty=x;
do
for(intv:G[y])
if(v!=son[y])
f[build(v)]=
y;// đệ quy thành tựu cũng liền nhẹ biên, chú ý muốn từ nhị xoa thụ căn liền biên, không phải từ nhi tử liền biên
while(y=son[y]);
y=0;
do{
b[y++]=x;// gửi trọng liên trung điểm
bs[y]=bs[y-1]+sz[x]-sz[son[x]];// bs: Nhẹ nhi tử size cùng +1, cầu tiền tố cùng
}while(x=son[x]);
returncbuild(0,y);
}

Từ số hiệu có thể thấy được thành tựu thời gian phức tạp độ là.Kế tiếp chúng ta có thể chứng minh thụ cao là:Suy xét từ tùy ý một cái điểm nhảy phụ tiết điểm đến căn. Nhảy nhẹ biên liền tương đương với ở nguyên thụ trung nhảy đến một khác điều trọng liên, từ trọng liên mổ phân tính chất nhưng đến nhảy nhẹ biên nhiều nhấtĐiều; bởi vì kiến nhị xoa thụ thời điểm căn tiết điểm tìm chính là tính nhẹ nhi tử thêm quyền điểm giữa, như vậy nhảy một lần trọng biên tính thượng nhẹ nhi tử size ít nhất phiên bội, cho nên nhảy trọng biên nhiều nhất cũng làĐiều. Chỉnh thể thụ thăng chức là.

Tuần tra

Trở lên chính là về toàn cục cân bằng nhị xoa thụ bộ phận. Dư lại về liên sửa chữa cùng liên tuần tra thao tác phương pháp tương đối đơn giản, chỉ cần từ muốn thao tác điểm xuất phát, vẫn luôn nhảy lên đến căn tiết điểm. Muốn thao tác nào đó điểm nơi trọng liên thượng so nó chiều sâu tiểu nhân sở hữu điểm, bản chất cùng cấp với tại đây điều trọng liên nhị xoa thụ trung thao tác mục tiêu tiết điểm bên trái sở hữu tiết điểm. Này đó thao tác có thể phân giải thành một loạt tử thụ thao tác, cùng bình thường nhị xoa thụ giữ gìn phương pháp cùng loại, trong đó đề cập đến giữ gìn tử thụ cùng cùng với đánh tử thụ đánh dấu. Tại đây một trong quá trình, sử dụng chính là đánh dấu vĩnh cửu hóa. Cũng có thể dùng pushdown tới đánh đánh dấu, dùng pushup giữ gìn tử thụ cùng, bất quá phương thức này khả năng tương đối phức tạp, bởi vì trong tình huống bình thường, xử lý nhị xoa thụ là từ trên xuống dưới tiến hành thao tác, nhưng ở chỗ này, yêu cầu đầu tiên xác định nhảy lên đường nhỏ, sau đó lại từ trên xuống dưới tiến hành pushdown, khả năng dẫn tới hằng số trọng đại.

Số hiệu như sau:

Thực hiện
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
// a: Tử thụ thêm đánh dấu
// s: Tử thụ cùng ( không tính thêm đánh dấu )
inta[N],s[N];

voidadd(intx){
boolt=true;
intz=0;
while(x){
s[x]+=z;
if(t){
a[x]++;
if(r[x])a[r[x]]--;
z+=1+ss[l[x]];
s[x]-=ss[r[x]];
}
t=(x!=l[f[x]]);
if(t&&x!=r[f[x]])z=0;// nhảy qua nhẹ biên muốn quét sạch
x=f[x];
}
}

intquery(intx){
intret=0;
boolt=true;
intz=0;
while(x){
if(t){
ret+=s[x]-s[r[x]];
ret-=1ll*ss[r[x]]*a[r[x]];
z+=1+ss[l[x]];
}
ret+=1ll*z*a[x];
t=(x!=l[f[x]]);
if(t&&x!=r[f[x]])z=0;// nhảy qua nhẹ biên muốn quét sạch
x=f[x];
}
returnret;
}

Ngoài ra, đối với tử thụ thao tác, chính là muốn suy xét nhẹ nhi tử, yêu cầu lại giữ gìn một cái bao gồm nhẹ nhi tử tử thụ cùng, tử thụ đánh dấu, có thể đi làm "P3384【 khuôn mẫu 】 nặng nhẹ liên mổ phân".

Ví dụ mẫu

P4751【 khuôn mẫu 】 "Động thái DP" & động thái thụ phân trị ( tăng mạnh bản )
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include&LTalgorithm>
#include&LTcstdio>
#include&LTcstring>
constexprintMAXN=1000000;
constexprintMAXM=3000000;
constexprintINF=0x3FFFFFFF;
usingnamespacestd;

structedge{
intto;
edge*nxt;
}edges[MAXN*2+5];

edge*ncnt=&edges[0],*Adj[MAXN+5];
intn,m;

structMatrix{
intM[2][2];

Matrixoperator*(constMatrix&B)const{
staticMatrixret;
for(inti=0;i2;i++)
for(intj=0;j2;j++){
ret.M[i][j]=-INF;
for(intk=0;k2;k++)
ret.M[i][j]=max(ret.M[i][j],M[i][k]+B.M[k][j]);
}
returnret;
}
}matr1[MAXN+5],matr2[MAXN+5];// mỗi cái điểm giữ gìn hai cái Ma trận

introot;
intw[MAXN+5],dep[MAXN+5],son[MAXN+5],siz[MAXN+5],lsiz[MAXN+5];
intg[MAXN+5][2],f[MAXN+5][2],trfa[MAXN+5],bstch[MAXN+5][2];
intstk[MAXN+5],tp;
boolvis[MAXN+5];

voidAddEdge(intu,intv){
edge*p=++ncnt;
p->to=v;
p->nxt=Adj[u];
Adj[u]=p;

edge*q=++ncnt;
q->to=u;
q->nxt=Adj[v];
Adj[v]=q;
}

voidDFS(intu,intfa){
siz[u]=1;
for(edge*p=Adj[u];p!=NULL;p=p->nxt){
intv=p->to;
if(v==fa)continue;
dep[v]=dep[u]+1;
DFS(v,u);
siz[u]+=siz[v];
if(!son[u]||siz[son[u]]siz[v])son[u]=v;
}
lsiz[u]=siz[u]-siz[son[u]];// nhẹ nhi tử siz cùng +1
}

voidDFS2(intu,intfa){
f[u][1]=w[u],f[u][0]=0;
g[u][1]=w[u],g[u][0]=0;
if(son[u]){
DFS2(son[u],u);
f[u][0]+=max(f[son[u]][0],f[son[u]][1]);
f[u][1]+=f[son[u]][0];
}
for(edge*p=Adj[u];p!=NULL;p=p->nxt){
intv=p->to;
if(v==fa||v==son[u])continue;
DFS2(v,u);
f[u][0]+=max(f[v][0],f[v][1]);// f[][] chính là bình thường DP số tổ
f[u][1]+=f[v][0];
g[u][0]+=max(f[v][0],f[v][1]);// g[][] số tổ chỉ thống kê chính mình cùng nhẹ nhi tử tin tức
g[u][1]+=f[v][0];
}
}

voidPushUp(intu){
matr2[u]=matr1[u];// matr1 là đơn điểm hơn nữa nhẹ nhi tử tin tức, matr2 là khu gian tin tức
if(bstch[u][0])matr2[u]=matr2[bstch[u][0]]*matr2[u];
// chú ý dời đi phương hướng, nhưng là nếu chúng ta củ thừa định nghĩa bất đồng, khả năng phương hướng cũng sẽ bất đồng
if(bstch[u][1])matr2[u]=matr2[u]*matr2[bstch[u][1]];
}

intgetmx2(intu){returnmax(matr2[u].M[0][0],matr2[u].M[0][1]);}

intgetmx1(intu){returnmax(getmx2(u),matr2[u].M[1][0]);}

intSBuild(intl,intr){
if(l>r)return0;
inttot=0;
for(inti=l;ir;i++)tot+=lsiz[stk[i]];
for(inti=l,sumn=lsiz[stk[l]];ir;i++,sumn+=lsiz[stk[i]])
if(sumn*2>=tot)// là trọng tâm
{
intlch=SBuild(l,i-1),rch=SBuild(i+1,r);
bstch[stk[i]][0]=lch;
bstch[stk[i]][1]=rch;
trfa[lch]=trfa[rch]=stk[i];
PushUp(stk[i]);// đem khu gian tin tức thống kê đi lên
returnstk[i];
}
return0;
}

intBuild(intu){
for(intpos=u;pos;pos=son[pos])vis[pos]=true;
for(intpos=u;pos;pos=son[pos])
for(edge*p=Adj[pos];p!=NULL;p=p->nxt)
if(!vis[p->to])// là nhẹ nhi tử
{
intv=p->to,ret=Build(v);
trfa[ret]=pos;// nhẹ nhi tử treefa[] tiếp đi lên
}
tp=0;
for(intpos=u;pos;pos=son[pos])stk[++tp]=pos;// đem trọng liên lấy ra
intret=SBuild(1,tp);// đối trọng liên tiến hành đơn độc SBuild( ta đoán là Special Build?)
returnret;// phản hồi trước mặt trọng liên nhị xoa thụ căn
}

voidModify(intu,intval){
matr1[u].M[1][0]+=val-w[u];
w[u]=val;
for(intpos=u;pos;pos=trfa[pos])
if(trfa[pos]&&bstch[trfa[pos]][0]!=pos&&bstch[trfa[pos]][1]!=pos){
matr1[trfa[pos]].M[0][0]-=getmx1(pos);
matr1[trfa[pos]].M[0][1]=matr1[trfa[pos]].M[0][0];
matr1[trfa[pos]].M[1][0]-=getmx2(pos);
PushUp(pos);
matr1[trfa[pos]].M[0][0]+=getmx1(pos);
matr1[trfa[pos]].M[0][1]=matr1[trfa[pos]].M[0][0];
matr1[trfa[pos]].M[1][0]+=getmx2(pos);
}else
PushUp(pos);
}

intread(){
intret=0,f=1;
charc=0;
while(c'0'||c>'9'){
c=getchar();
if(c=='-')f=-f;
}
ret=10*ret+c-'0';
while(true){
c=getchar();
if(c'0'||c>'9')break;
ret=10*ret+c-'0';
}
returnret*f;
}

voidprint(intx){
if(x==0)return;
print(x/10);
putchar(x%10+'0');
}

intmain(){
scanf("%d %d",&n,&m);
for(inti=1;in;i++)w[i]=read();
intu,v;
for(inti=1;in;i++){
u=read(),v=read();
AddEdge(u,v);
}
DFS(1,-1);
// cầu trọng nhi tử
DFS2(1,-1);
// cầu mới bắt đầu DP giá trị, cũng có thể ở Build() bên trong cầu, nhưng là như vậy viết liền cùng thụ mổ phương pháp sáng tác thống nhất
for(inti=1;in;i++){
matr1[i].M[0][0]=matr1[i].M[0][1]=g[i][0];
matr1[i].M[1][0]=g[i][1],matr1[i].M[1][1]=-INF;// khởi động lại Ma trận
}
root=Build(1);// root tức làm gốc tiết điểm nơi trọng liên trọng tâm
intlastans=0;
for(inti=1;im;i++){
u=read(),v=read();
u^=lastans;// cưỡng chế tại tuyến
Modify(u,v);
lastans=getmx1(root);// trực tiếp lấy giá trị
if(lastans==0)
putchar('0');
else
print(lastans);
putchar('\n');
}
return0;
}

Tham khảo

P4211 [LNOI2014] LCA | toàn cục cân bằng nhị xoa thụ