此题的完成,代表近期的树链剖分就告一段落,全力进入联赛复习。
省选day2 的第二题,当时只是写了裸的bfs,TE到家了。
4个月后学长偶然的一句:树链剖分也可以,考试的时候就vfk一个人想到了。。。
如今看来,vfk走出考场说“今天三个题都是暴力”,是正确的。
由于每次改变根节点,那么这个到1的路径上的点才有可能更新。
当根节点由0变为1时,只会对上一个节点是1的点有影响,如果不是1直接更新这个点就可以了。
反过来 一个根节点由1变为0时,只会对上一个节点是2的产生影响。
val记录这个点有几个值为1的儿子
可是线段树如何介入呢。
这就是vfk的那句暴力了。
如果这个点由0变为了1,那么他所有的父节点中连续的只有一个子节点为1 即val[ i ]==1的点的值都会变为1;
如果这个点由1变为了0,那么他所有的父节点中连续的只有两个子节点为1 即val[ i ]==2的点的值都会变为0;
(建议自己画个图看一下)
这里就把O(n)的修改降为了O(logn);
所以线段树只需维护区间左右连续的值的长度即可。
每一次update后都要判断有没有到根节点。
/**************************************************************
Problem: 3553
User: xujiahe
Language: C++
Result: Accepted
Time:23080 ms
Memory:175812 kb
****************************************************************/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
#define maxn 2100000
#define ll long long
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define ss printf("orz\n")
inline int readint()
{
int flag=0;
char ch = getchar();
int data = 0;
while (ch < '0' || ch > '9')
{
if(ch=='-') flag=1;
ch = getchar();
}
do
{
data = data*10 + ch-'0';
ch = getchar();
}while (ch >= '0' && ch <= '9');
if(flag) data=-data;
return data;
}
int fa[maxn],siz[maxn],top[maxn],w[maxn],son[maxn],dep[maxn],id,dy[maxn],nn,val2[maxn];
struct node
{
int v,next;
}g[maxn];
int num,n,first[maxn],val[maxn];
int tree[maxn],col[maxn],lcol[maxn],rcol[maxn],lmax[maxn],rmax[maxn],sum[maxn];
void build(int a,int b)
{
num++;
g[num].v=b;
g[num].next=first[a];
first[a]=num;
}
void dfs(int now)
{
if (now>nn) return;
int v,ceng;
int maxv=0,flag=0,tmp=0;
siz[now]=1;
for(int i=first[now];i;i=g[i].next)
{
v=g[i].v;
if(v==fa[now]) continue;
dfs(v);
dep[v]=dep[now]+1;
fa[v]=now;
val2[now]+=val[v];
if(val[v])
{
tmp++;
}
siz[now]+=siz[v];
if(siz[v]>maxv)
{
maxv=siz[v];
flag=v;
}
}
son[now]=flag;
if(tmp>1)
val[now]=1;
else
val[now]=0;
}
void getid(int now,int root)
{
if(now>nn) return;
w[now]=++id;
top[now]=root;
dy[id]=now;
if(son[now]) getid(son[now],top[now]);
for(int i=first[now]; i; i=g[i].next)
{
if(g[i].v!=son[now]&&g[i].v!=fa[now])
{
getid(g[i].v,g[i].v);
}
}
}
void pushdown(int rt)
{
if(col[rt]!=0)
{
col[rt<<1]+=col[rt];
col[rt<<1|1]+=col[rt];
lcol[rt<<1]+=col[rt];
rcol[rt<<1]+=col[rt];
lcol[rt<<1|1]+=col[rt];
rcol[rt<<1|1]+=col[rt];
col[rt]=0;
}
}
void pushup(int rt,int len)
{
lmax[rt]=lmax[rt<<1];
if(lmax[rt<<1]==(len-(len>>1))&&rcol[rt<<1]==lcol[rt<<1|1])
{
lmax[rt]+=lmax[rt<<1|1];
}
rmax[rt]=rmax[rt<<1|1];
if(rmax[rt<<1|1]==(len>>1)&&rcol[rt<<1]==lcol[rt<<1|1])
{
rmax[rt]+=rmax[rt<<1];
}
lcol[rt]=lcol[rt<<1];
rcol[rt]=rcol[rt<<1|1];
}
void buildt(int rt,int l,int r)
{
int m=(l+r)>>1;
if(l==r)
{
lmax[rt]=rmax[rt]=1;
lcol[rt]=rcol[rt]=val2[dy[l]];
return ;
}
buildt(lson);
buildt(rson);
pushup(rt,r-l+1);
}
int getval(int rt,int l,int r,int x)
{
int m=(l+r)>>1;
if(l==r)
{
return lcol[rt];
}
pushdown(rt);
if(x<=m)
{
return getval(lson,x);
}
else
{
return getval(rson,x);
}
}
int getlen(int rt,int l,int r,int x,int y)
{
if(x==l&&y==r)
{
return rmax[rt];
}
pushdown(rt);
int tmp=0;
int m=(l+r)>>1;
if(y<=m)
{
return getlen(lson,x,y);
}
else if(x>m)
{
return getlen(rson,x,y);
}
else
{
tmp=getlen(rson,m+1,y);
if (tmp<y-m||rcol[rt<<1]!=lcol[rt<<1|1]) return tmp;
else return tmp+getlen(lson,x,m);
}
}
void update(int rt,int l,int r,int x,int y,int c)
{
if(x==l&&y==r)
{
lcol[rt]+=c;
rcol[rt]+=c;
col[rt]+=c;
return;
}
pushdown(rt);
int m=(l+r)>>1;
if(y<=m)
{
update(lson,x,y,c);
}
else if(x>m)
{
update(rson,x,y,c);
}
else
{
update(lson,x,m,c);
update(rson,m+1,y,c);
}
pushup(rt,r-l+1);
}
void getans(int x,int op)
{
int xx=x;
if(op==1)
{
while(x)
{
if(getval(1,1,n,w[x])!=1)
{
update(1,1,n,w[x],w[x],1);
break;
}
int len=getlen(1,1,n,w[top[x]],w[x]);
update(1,1,n,max(w[x]-len+1,1),w[x],1);
if (max(w[x]-len+1,1)!=1 && len!=w[x]-w[top[x]]+1)
{
update(1,1,n,w[fa[dy[w[x]-len+1]]],w[fa[dy[w[x]-len+1]]],1);
}
if (len!=w[x]-w[top[x]]+1) break;
x=fa[top[x]];
}
}
else
{
while(x)
{
if(getval(1,1,n,w[x])!=2)
{
update(1,1,n,w[x],w[x],-1);
break;
}
int len=getlen(1,1,n,w[top[x]],w[x]);
update(1,1,n,max(w[x]-len+1,1),w[x],-1);
if (max(w[x]-len+1,1)!=1 && len!=w[x]-w[top[x]]+1)
{
update(1,1,n,w[fa[dy[w[x]-len+1]]],w[fa[dy[w[x]-len+1]]],-1);
}
if (len!=w[x]-w[top[x]]+1) break;
x=fa[top[x]];
}
}
}
int main()
{
char str[20];
int a,b,c,m;
n=readint();
nn=n;
for(int i=1;i<=n;i++)
{
a=readint();
b=readint();
c=readint();
build(i,a);
build(i,b);
build(i,c);
}
for(int i=1;i<=2*n+1;i++)
{
val[i+n]=readint();
}
n=n*3+1;
fa[1]=0;
dfs(1);
getid(1,1);
int x,y,z;
n=nn;
memset(col,0,sizeof(col));
buildt(1,1,n);
m=readint();
while(m--)
{
x=readint();
if(val[x]==0)
{
val[x]^=1;
getans(fa[x],1);
}
else
{
val[x]^=1;
getans(fa[x],2);
}
printf("%d\n",getval(1,1,n,1)>1);
}
return 0;
}
/*
3
2 3 4
5 6 7
8 9 10
0 0 0 0 1 1 1
5
4
4
5
6
8
1
0
0
1
1
*/