HYSBZ/BZOJ 1036 [ZJOI2008] 树的统计Count - 动态树LCT
看着就是个LCT的模板题,可惜忘记在change的时候Update了,最终爆零!悲惨经历,教训啊。
题目有坑:
1. 有负数,要么最开始全部赋值为-INF,否则要判断儿子是否为0
2. Link之后要Update,Change之后要Update,Rotate之后要Update,Splay之后要Update,Access要Update.
3. Access之后不要忘了Splay(u),Splay之前不要忘了Push_up()
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 30000
struct node{
int ch[2],fa,path_fa;
int flip,mx,sum;
}tre[MAXN+10];
int n,wt[MAXN+10],l[MAXN+10][3];
char s[20];
void Push_down(int u)
{
if(!tre[u].flip)
return ;
tre[u].flip=0;
swap(tre[u].ch[0],tre[u].ch[1]);
if(tre[u].ch[0])
tre[tre[u].ch[0]].flip^=1;
if(tre[u].ch[1])
tre[tre[u].ch[1]].flip^=1;
}
void Push_up(int x)
{
if(tre[x].fa)
Push_up(tre[x].fa);
Push_down(x);
}
void Update(int u)
{
if(!u) return ;
tre[u].mx=tre[u].sum=wt[u];
if(tre[u].ch[0]){
tre[u].mx=max(tre[u].mx,tre[tre[u].ch[0]].mx);
tre[u].sum+=tre[tre[u].ch[0]].sum;
}
if(tre[u].ch[1]){
tre[u].mx=max(tre[u].mx,tre[tre[u].ch[1]].mx);
tre[u].sum+=tre[tre[u].ch[1]].sum;
}
}
void Rotate(int x,int d) //RotateRight d=1 RotateLeft d=0
{
int y=tre[x].fa,fa=tre[y].fa;
tre[y].ch[d^1]=tre[x].ch[d];
if(tre[x].ch[d])
tre[tre[x].ch[d]].fa=y;
tre[x].ch[d]=y,tre[y].fa=x;
tre[x].fa=fa;
if(fa){
if(y==tre[fa].ch[0]) tre[fa].ch[0]=x;
else tre[fa].ch[1]=x;
}
tre[x].path_fa=tre[y].path_fa;
tre[y].path_fa=0;
Update(y);
}
void Splay(int x)
{
Push_up(x);
while(!tre[x].path_fa&&tre[x].fa){
int y=tre[x].fa,z=tre[y].fa;
if(tre[y].path_fa||!tre[y].fa){
if(x==tre[y].ch[0]) Rotate(x,1);
else Rotate(x,0);
}
else{
if(y==tre[z].ch[0]){
if(x==tre[y].ch[0])
Rotate(y,1),Rotate(x,1);
else
Rotate(x,0),Rotate(x,1);
}
else{
if(x==tre[y].ch[0])
Rotate(x,1),Rotate(x,0);
else
Rotate(y,0),Rotate(x,0);
}
}
}
Update(x);
}
void Access(int u)
{
int x=u,y=0;
while(x){
Splay(x);
int v=tre[x].ch[1];
if(v){
tre[v].fa=0;
tre[v].path_fa=x;
}
tre[x].ch[1]=y;
if(y){
tre[y].path_fa=0;
tre[y].fa=x;
}
Update(x);
y=x;
x=tre[y].path_fa;
}
Splay(u);
}
void Link(int x,int y)
{
Access(x);
Access(y);
tre[x].flip^=1;
tre[y].ch[1]=x;
tre[x].fa=y,tre[x].path_fa=0;
Update(y);
}
void Quary(int a,int b,int &q1,int &q2)
{
Access(a);
int x=b,y=0;
while(x){
Splay(x);
if(!tre[x].path_fa){
q1=q2=wt[x];
if(tre[x].ch[1]){
q1=max(tre[tre[x].ch[1]].mx,q1);
q2+=tre[tre[x].ch[1]].sum;
}
if(y){
q1=max(q1,tre[y].mx);
q2+=tre[y].sum;
}
return ;
}
int v=tre[x].ch[1];
if(v){
tre[v].fa=0;
tre[v].path_fa=x;
}
tre[x].ch[1]=y;
if(y){
tre[y].fa=x;
tre[y].path_fa=0;
}
Update(x);
y=x;
x=tre[y].path_fa;
}
}
int main()
{
//freopen("count.in","r",stdin);
//freopen("count.out","w",stdout);
int x,y;
scanf("%d",&n);
for(int i=1;i<n;i++)
scanf("%d%d",&l[i][0],&l[i][1]);
for(int i=1;i<=n;i++){
scanf("%d",&wt[i]);
tre[i].mx=tre[i].sum=wt[i];
}
for(int i=1;i<n;i++)
Link(l[i][0],l[i][1]);
int Q,q1,q2;
scanf("%d",&Q);
while(Q--){
scanf("%s%d%d",s,&x,&y);
if(s[0]=='C'){
Access(x);
wt[x]=y;
Update(x);
}
else if(s[1]=='M'){
Quary(x,y,q1,q2);
printf("%d\n",q1);
}
else{
Quary(x,y,q1,q2);
printf("%d\n",q2);
}
}
}