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 ...
随机推荐
- jieba
# coding: utf-8 # ###jieba特性介绍 # 支持三种分词模式: # 精确模式,试图将句子最精确地切开,适合文本分析: # 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非 ...
- Feature hashing相关 - 1
考虑典型的文本分类,一个经典的方法就是 分词,扫描所有特征,建立特征词典 重新扫描所有特征,利用特征词典将特征映射到特征空间编号 得到特征向量 学习参数 w 存储学习参数 w , 存储特征映射 ...
- 微信支付开发(1) JS API支付V3版(转)
http://www.cnblogs.com/txw1958/p/wxpayv3-jsapi.html 本文介绍微信支付下的jsapi实现流程 前言 微信支付现在分为v2版和v3版,2014年9月10 ...
- 【转载】Python编写简易木马程序
转载来自: http://drops.wooyun.org/papers/4751?utm_source=tuicool 使用Python编写一个具有键盘记录.截屏以及通信功能的简易木马. 首先准备好 ...
- HDU2205 又见回文(区间DP)
题意:给定两个字符串(可能为空串),求这两个串交叉组成新串的子串中的回文串的最大长度. 布尔型变量dp[i][j][k][l]表示串a从i到j,b从k到l能否组成新串,初始化为false,则采取区间动 ...
- 【leetcode】Candy
题目描述: There are N children standing in a line. Each child is assigned a rating value. You are giving ...
- hdu 4045 2011北京赛区网络赛F 组合数+斯特林数 ***
插板法基础知识 斯特林数见百科 #include<iostream> #include<cmath> #include<cstdio> #include<cs ...
- NDK-gdb
http://www.gnu.org/software/gdb/download/ http://mhandroid.wordpress.com/2011/01/23/using-eclipse-fo ...
- BZOJ 3289: Mato的文件管理 莫队+BIT
3289: Mato的文件管理 Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的 ...
- HDU 3341 Lost's revenge(AC自动机+DP)
Lost's revenge Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)T ...