博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷P4332 [SHOI2014]三叉神经树(LCT)
阅读量:6379 次
发布时间:2019-06-23

本文共 3091 字,大约阅读时间需要 10 分钟。

 

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
3 #include
4 #include
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 num16 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]='\n';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

你可能感兴趣的文章
Swift_1_基本数据类型
查看>>
深入解析Vuex实战总结
查看>>
流水落花春去也
查看>>
【教训】为什么不作备份?!
查看>>
ThinkPHP3.0启动过程
查看>>
JAX-WS(JWS)发布WebService
查看>>
Centos7安装docker-compse踩过的坑
查看>>
细说Nullable<T>类型
查看>>
oracle 插入表数据的4种方式
查看>>
7.Ajax
查看>>
Linux vi/vim编辑器常用命令与用法总结
查看>>
对于 url encode decode js 和 c# 有差异
查看>>
mysql 修改列为not null报错Invalid use of NULL value
查看>>
epoll源码分析
查看>>
朱晔和你聊Spring系列S1E4:灵活但不算好用的Spring MVC
查看>>
Java使用Try with resources自动关闭资源
查看>>
china-pub十一周年庆,多重优惠隆重登场,千万别错过哟!
查看>>
HDU 3068 最长回文(manacher算法)
查看>>
二叉树
查看>>
手把手教你如何安装水晶易表——靠谱的安装教程
查看>>