BZOJ3553 : [Shoi2014]三叉神经树
设val[i]为i连出去的树突中输出值为0的个数
如果val[x]<=1,输出值为1,否则输出值为0
修改x就相当于val[f[i]]++或者val[f[i]]--
用Link-cut Tree维护这棵树,
每个节点维护val[x]、size[x](子树大小)、cnt1[x](子树里val[x]==1的个数)、cnt2[x](子树里val[x]==2的个数)
以val[f[i]]--为例:
设x=f[i]
access(x)取出x到根这条链
如果val[x]!=2,那么x的输出值不变,直接修改x即可
如果val[x]==2,那么影响到的肯定是一段连续的2以及最开头的2之前的那个点y
如果从根节点开始到x一直都是2,那么直接把这条链打上全部修改为1的标记即可
否则,因为这个具有单调性,所以可以二分这个y,
二分时方便起见二分深度,
对于当前二分到的mid,把深度为mid的点t splay上来
那么只要检验t的右子树是否符合cnt2[]==size[]就可以了
找到y之后splay(y),然后y的右子树里打上全部修改为1的标记,再把y单点修改即可
总复杂度$O(q\log^2n)$
#include<cstdio>
#define N 500010
int f[N*3],son[N][2],size[N],val[N],cnt1[N],cnt2[N],tag[N],a[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void swap(int&a,int&b){int c=a;a=b;b=c;}
inline bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
inline void same1(int x,int p){
if(!x)return;
val[x]=tag[x]=p;
if(p==1)cnt1[x]=size[x],cnt2[x]=0;else cnt2[x]=size[x],cnt1[x]=0;
}
inline void pb(int x){if(tag[x])same1(son[x][0],tag[x]),same1(son[x][1],tag[x]),tag[x]=0;}
inline void up(int x){
size[x]=size[son[x][0]]+size[son[x][1]]+1;
cnt1[x]=cnt1[son[x][0]]+cnt1[son[x][1]]+(val[x]==1);
cnt2[x]=cnt2[son[x][0]]+cnt2[son[x][1]]+(val[x]==2);
}
inline void rotate(int x){
int y=f[x],w=son[y][1]==x;
son[y][w]=son[x][w^1];
if(son[x][w^1])f[son[x][w^1]]=y;
if(f[y]){
int z=f[y];
if(son[z][0]==y)son[z][0]=x;
if(son[z][1]==y)son[z][1]=x;
}
f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
}
inline void splay(int x){
int s=1,i=x,y;a[1]=i;
while(!isroot(i))a[++s]=i=f[i];
while(s)pb(a[s--]);
while(!isroot(x)){
y=f[x];
if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
rotate(x);
}
up(x);
}
inline void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);}
inline int kth(int x,int k){
while(1){
if(k==size[son[x][0]]+1)return x;
if(k<=size[son[x][0]])x=son[x][0];else k-=size[son[x][0]]+1,x=son[x][1];
}
}
inline void dec(int x){
access(x);splay(x);
if(x==1||val[x]!=2){val[x]--;up(x);return;}
if(size[x]==cnt2[x]){same1(x,1);return;}
int y=0,l=1,r=size[x]-1,mid,t=x;
while(l<=r){
mid=(l+r)>>1;
splay(t=kth(t,mid));
if(cnt2[son[t][1]]==size[son[t][1]])y=t,r=mid-1;else l=mid+1;
}
splay(y);same1(son[y][1],1);val[y]--;up(y);
}
inline void inc(int x){
access(x);splay(x);
if(x==1||val[x]!=1){val[x]++;up(x);return;}
if(size[x]==cnt1[x]){same1(x,2);return;}
int y=0,l=1,r=size[x]-1,mid,t=x;
while(l<=r){
mid=(l+r)>>1;
splay(t=kth(t,mid));
if(cnt1[son[t][1]]==size[son[t][1]])y=t,r=mid-1;else l=mid+1;
}
splay(y);same1(son[y][1],2);val[y]++;up(y);
}
int n,i,x,j,g[N*3],nxt[N*6],v[N*6],ed,q,show[N*3];
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x,int pre){
f[x]=pre;
if(x>n)return;
for(int i=g[x];i;i=nxt[i])if(v[i]!=pre){
dfs(v[i],x);
if(!show[v[i]])val[x]++;
}
show[x]=val[x]<=1;
}
int main(){
for(read(n),i=1;i<=n;i++)for(size[i]=1,j=0;j<3;j++)read(x),add(i,x),add(x,i);
for(i=n+1;i<=3*n+1;i++)read(show[i]);
dfs(1,0);
read(q);
while(q--){
read(x);
if(show[x])inc(f[x]);else dec(f[x]);show[x]^=1;
splay(1);
printf("%d\n",val[1]<=1);
}
return 0;
}
BZOJ3553 : [Shoi2014]三叉神经树的更多相关文章
- [BZOJ 3553][SHOI2014]三叉神经树
传送门(下面也有题面) 题目大意: 一颗有根树,每个非叶子节点都有三个子节点,每个节点的权为0/1. 每个节点的权 取决于其所有子节点中 哪种权出现的次数更多. 有若干次询问,每次询问修改一个叶子节点 ...
- 【BZOJ-3553】三叉神经树 树链剖分
3553: [Shoi2014]三叉神经树 Time Limit: 160 Sec Memory Limit: 256 MBSubmit: 347 Solved: 112[Submit][Stat ...
- 3553: [Shoi2014]三叉神经树(树链剖分)
这道题特别恶心,首先我们可以发现更改的就是出现连续的一或二,那么就用线段树+树链剖分找到这个范围 想到是不难想,就是打起来恶心罢了= = CODE: #include<cstdio> #i ...
- [SHOI2014]三叉神经树
题目描述 计算神经学作为新兴的交叉学科近些年来一直是学术界的热点.一种叫做SHOI 的神经组织因为其和近日发现的化合物 SHTSC 的密切联系引起了人们的极大关注. SHOI 组织由若干个 SHOI ...
- 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)
洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...
- P4332 [SHOI2014]三叉神经树(LCT)
Luogu4332 LOJ2187 题解 代码-Tea 题意 : 每个点有三个儿子 , 给定叶节点的权值\(0\)或\(1\)且支持修改 , 非叶子节点的权值为当有\(>=2\)个儿子的权值为\ ...
- P4332 [SHOI2014]三叉神经树
\(\color{#0066ff}{ 题目描述 }\) 计算神经学作为新兴的交叉学科近些年来一直是学术界的热点.一种叫做SHOI 的神经组织因为其和近日发现的化合物 SHTSC 的密切联系引起了人们的 ...
- 洛谷P4332 [SHOI2014]三叉神经树(LCT)
传送门 FlashHu大佬太强啦%%% 首先,我们可以根据每一个点的权值为$1$的儿子的个数把每个点记为$0~3$,表示这一个点的点权 先考虑一下暴力的过程,假设从$0$变为$1$,先更改一个叶子结点 ...
- BZOJ 3553: [Shoi2014]三叉神经树 LCT
犯傻了,想到了如果是 0->1 的话就找最深的非 1 编号,是 1 -> 0 的话就找最深的非 0 编号. 但是没有想到这个东西可以直接维护. 假设不考虑叶子节点,那么如果当前点的值是 1 ...
随机推荐
- 谈谈Delphi中的类和对象1---介绍几个概念 && 对象是一个地地道道的指针
参考:http://blog.163.com/liang_liu99/blog/static/88415216200952123412180/ 以下的介绍主要针对的是Delphi的面向对象的知识,可能 ...
- at org.apache.jsp.index_jsp._jspInit(index_jsp.java:22) 报空指针
原来发布到weblogic 的项目,想改动发布到tomcat上.启动发布一切都正常.出入项目请求路径却包错: java.lang.NullPointerException at org.apache. ...
- [LeetCode] Binary Tree Preorder Traversal
Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binary tr ...
- [LeetCode] Rotate Image
You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwise). ...
- PHP+MYSQL+AJAX实现每日签到功能
一.web前端及ajax部分 文件index.html <html> <head> <meta http-equiv=Content-Type content=" ...
- Git提交基本流程
在无其他分支,大家都向同一分支master分支提交代码的情况下: 1.查看本地对代码的修改情况,即可以被提交的修改记录 git status 其中被修改过的文件标识为modified,删除的文件del ...
- LeetCode——Reverse Integer(逆置一个整数)
问题: Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, return –321 Ha ...
- 学习linux内核时常碰到的汇编指令(1)
转载:http://blog.sina.com.cn/s/blog_4be6adec01007xvg.html 80X86 汇编指令符号大全 +.-.*./∶算术运算符. &∶宏处理操作符. ...
- HDFS & MapReduce异构存储性能测试白皮书
- Linux环境变量设置指南
以配置java环境变量为例 目录 [隐藏] 1 修改/etc/profile文件 2 修改用户目录下的.bash_profile 3 修改.bashrc文件 4 直接在shell下设置 5 查看环境 ...