洛谷P4332 [SHOI2014]三叉神经树(LCT)

传送门

FlashHu大佬太强啦%%%

首先,我们可以根据每一个点的权值为$1$的儿子的个数把每个点记为$0~3$,表示这一个点的点权

先考虑一下暴力的过程,假设从$0$变为$1$,先更改一个叶子结点,然后不断地往上更新,如果更改之后父亲的儿子中权值为$1$的儿子个数大于权值为$0$的儿子个数,那么就继续更新父亲,直到不能更新为止

不难发现,我们每一个更改的都是树上的一条链。而且,只有当点权为$1$时,才能因为修改使点权变为$2$,使输出改变,从而更新祖先。那么,我们需要的就是对于每一个节点,从它向上的连续的点权为$1$的一部分

如果是从$1$变为$0$同理,我们要维护从每一个节点向上的连续的点权为$2$的一部分

那么我们对于每一个节点,先access,然后记录splay中最深的点权不为$1$和$2$的点,然后把它给splay到根,再对右子树进行区间修改,对他自己单点修改

然后注意特判,如果整棵splay里都没有点权不为$1$或$2$的点,那么直接区间修改

然后怎么记录点权嘞?我们先把所有叶子结点的值*2,那么只有0和2两种值,然后每一个节点只要加上它所有叶子结点的值/2就是这个点的点权了

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 7 char buf[1<<21],*p1=buf,*p2=buf;
 8 inline int read(){
 9     #define num ch-'0'
10     char ch;bool flag=0;int res;
11     while(!isdigit(ch=getc()))
12     (ch=='-')&&(flag=true);
13     for(res=num;isdigit(ch=getc());res=res*10+num);
14     (flag)&&(res=-res);
15     #undef num
16     return res;
17 }
18 char sr[1<<21];int C=-1;
19 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
20 inline void print(int x){
21     sr[++C]=x|48,sr[++C]='
';
22 }
23 const int N=500005,M=1500005;
24 int fa[M],ch[N][2],n1[N],n2[N],tag[N],v[M];
25 int d[N],q[M],h=1,t,ans;
26 #define ls ch[x][0]
27 #define rs ch[x][1]
28 inline bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
29 inline void pup(int x){
30     //先右儿子再自己最后左儿子
31     //因为&是短路运算符,有一个为假就会自动跳出 
32     if(!(n1[x]=n1[rs])&&!(n1[x]=x*(v[x]!=1))) n1[x]=n1[ls];
33     if(!(n2[x]=n2[rs])&&!(n2[x]=x*(v[x]!=2))) n2[x]=n2[ls];
34 }
35 inline void pdown(int x,int t){
36     //被区间修改的要么都是1要么都是2,直接反转信息
37     v[x]^=3,swap(n1[x],n2[x]),tag[x]+=t;
38 }
39 void all(int x){
40     if(!isrt(x)) all(fa[x]);
41     if(tag[x]) pdown(ls,tag[x]),pdown(rs,tag[x]),tag[x]=0;
42 }
43 void rotate(int x){
44     int y=fa[x],z=fa[y],d=ch[y][1]==x;
45     if(!isrt(y)) ch[z][ch[z][1]==y]=x;
46     fa[x]=z,fa[y]=x,fa[ch[x][d^1]]=y,ch[y][d]=ch[x][d^1],ch[x][d^1]=y,pup(y);
47 }
48 void splay(int x){
49     all(x);
50     for(int y=fa[x],z=fa[y];!isrt(x);y=fa[x],z=fa[y]){
51         if(!isrt(y))
52         ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y);
53         rotate(x);
54     }
55     pup(x);
56 }
57 inline void access(int x){
58     for(int y=0;x;x=fa[y=x])
59     splay(x),rs=y,pup(x);
60 }
61 int main(){
62 //    freopen("testdata.in","r",stdin);
63     int n=read();
64     for(int i=1;i<=n;++i)
65     d[fa[read()]=fa[read()]=fa[read()]=i]=3;
66     for(int i=n+1;i<=3*n+1;++i) v[q[++t]=i]=read()<<1;
67     while(h<=t){
68         int x=q[h++];if(x<=n) pup(x);
69         v[fa[x]]+=v[x]>>1;
70         if(!(--d[fa[x]])) q[++t]=fa[x];
71     }
72     ans=v[1]>>1;
73     int q=read();
74     while(q--){
75         int x=read(),k=(v[x]^=2)-1;
76         access(x=fa[x]),splay(x);
77         if(~k?n1[x]:n2[x]){
78             splay(x=(~k?n1[x]:n2[x]));
79             pdown(rs,k),pup(rs);
80             v[x]+=k,pup(x);
81         }
82         else pdown(x,k),pup(x),ans^=1;
83         print(ans);
84     }
85     Ot();
86     return 0;
87 }
原文地址:https://www.cnblogs.com/bztMinamoto/p/9613787.html