题目大意:给你一棵树,除了叶子结点外每个点的都是三个儿子,每个结点都有一个状态0 or 1,每个非叶子结点的状态是其儿子中较多的那种,叶子结点的状态是给定的,支持修改与查询操作,即改变一个叶子结点的状态,或者查询根结点的状态。 n<=500000 m<=500000
首先,树链剖分一下(叶子结点不要管),然后对于线段树上维护每个结点的状态(儿子中有几个是1),然后如果是把一个点从0改成1,那么就查询从他父亲到根结点最近的不是(1,0,0)的点x,然后把它到x的全改为(1,1,0),然后查询x->fa的状态,然后修改成多一个1的状态。1改0的话类似。。。
查询的话,就是线段树中单点查询了
线段树中只需要维护右起最长连续的(0,0,1),与右起最长连续的(0,1,1)就ok了
复杂度的话 修改log^2n,查询logn
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=500011,maxm=1500011,ncov=-1;
inline void read(int &x){
x=0; char ch=getchar();
while (!isdigit(ch)) ch=getchar();
for (;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
}
inline void read_(int &x){
char ch=getchar(); while (!isdigit(ch)) ch=getchar(); x=ch-'0';
}
int map[maxn][3],v[maxm],fa[maxm],n;
void init(){
read(n);
for (int i=1;i<=n;++i) for (int j=0;j<3;++j) read(map[i][j]),fa[map[i][j]]=i;
for (int i=n+1,m=3*n+1;i<=m;++i) read_(v[i]),v[fa[i]]+=v[i];
}
int dep[maxn],top[maxn],sz[maxn],dfn[maxn],seq[maxn];
void getseq(){
static int q[maxn]; dep[1]=1; fa[1]=0; q[1]=1;
for (int i=1,w=1;i<=n;++i) for (int j=0;j<3;++j) if (map[q[i]][j]<=n)
q[++w]=map[q[i]][j],dep[q[w]]=dep[q[i]]+1;
for (int i=1;i<=n;++i) top[i]=i,sz[i]=1;
for (int i=n;i>=1;--i) sz[fa[q[i]]]+=sz[q[i]]; sz[0]=0; dfn[1]=1;
for (int i=1;i<=n;++i){
int x=q[i],res=dfn[x],tmp=0;
for (int j=0;j<3;++j) if (map[x][j]<=n && sz[map[x][j]]>sz[tmp]) tmp=map[x][j];
if (tmp){dfn[tmp]=res+1; res+=sz[tmp]; top[tmp]=top[x];}
for (int j=0;j<3;++j) if (map[x][j]<=n && map[x][j]!=tmp)
dfn[map[x][j]]=res+1,res+=sz[map[x][j]];
}
for (int i=1;i<=n;++i)
assert(dfn[i]>=0 && dfn[i]<=n && dep[i]>0 && sz[i]>0 && top[i]>0 && sz[i]<=n && top[i]<=n);
for (int i=n;i>=1;--i) if (v[q[i]]>=2) ++v[fa[q[i]]];
for (int i=1;i<=n;++i) seq[dfn[i]]=i;
}
struct Tseg{
struct node{
int mx[2],c,sz; // mx[0]代表(0,0,1)的右起连续最长,mx[1]代表(0,1,1)的
void cov(int c_){
c=c_; mx[0]=mx[1]=0; if (c==1) mx[0]=sz; if (c==2) mx[1]=sz;
}
}t[maxn<<3];
void update(node &p,node ls,node rs){
p.sz=ls.sz+rs.sz; p.mx[0]=rs.mx[0]; p.mx[1]=rs.mx[1];
if (rs.mx[0]==rs.sz) p.mx[0]+=ls.mx[0];
if (rs.mx[1]==rs.sz) p.mx[1]+=ls.mx[1];
}
void pushdown(int p){
if (t[p].c==ncov) return;
t[p<<1].cov(t[p].c); t[p<<1|1].cov(t[p].c); t[p].c=ncov;
}
void build(int p,int l,int r){
t[p].c=ncov; if (l==r){t[p].sz=1; t[p].cov(v[seq[l]]); return;}
int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r);
update(t[p],t[p<<1],t[p<<1|1]);
}
void clear(){build(1,1,n);}
int Query(int p,int l,int r,int m){
if (l==r){assert(l==m); return t[p].c;}
pushdown(p); int mid=(l+r)>>1;
if (m<=mid) return Query(p<<1,l,mid,m);
return Query(p<<1|1,mid+1,r,m);
}
node Query(int p,int l,int r,int fir,int las){
if (l==fir && r==las) return t[p];
pushdown(p); int mid=(l+r)>>1;
if (las<=mid) return Query(p<<1,l,mid,fir,las);
if (fir>mid) return Query(p<<1|1,mid+1,r,fir,las);
node res; update(res,Query(p<<1,l,mid,fir,mid),Query(p<<1|1,mid+1,r,mid+1,las));
return res;
}
void modify(int p,int l,int r,int fir,int las,int c){
if (l==fir && r==las) {t[p].cov(c); return;}
pushdown(p); int mid=(l+r)>>1;
if (las<=mid) modify(p<<1,l,mid,fir,las,c);
else if (fir>mid) modify(p<<1|1,mid+1,r,fir,las,c);
else modify(p<<1,l,mid,fir,mid,c),modify(p<<1|1,mid+1,r,mid+1,las,c);
update(t[p],t[p<<1],t[p<<1|1]);
}
void modify(int x,int p,int c){
for (;top[x]!=top[p];x=fa[top[x]]) modify(1,1,n,dfn[top[x]],dfn[x],c);
modify(1,1,n,dfn[p],dfn[x],c);
}
int modify(int x){
int key=v[x]; v[x]=1-v[x];
// 把key变成1-key
int tmp=fa[x];
while (1){
node res=Query(1,1,n,dfn[top[tmp]],dfn[tmp]);
if (res.sz!=res.mx[key]) break; tmp=top[tmp];
if (!fa[tmp]) break;
if (Query(1,1,n,dfn[fa[tmp]])!=key+1) break; tmp=fa[tmp];
}
int p;
if (Query(1,1,n,dfn[tmp])!=key+1){
modify(1,1,n,dfn[tmp],dfn[tmp],Query(1,1,n,dfn[tmp])+(key?-1:1));
return Query(1,1,n,1)>=2;
}
if (tmp==top[tmp]) p=tmp;
else p=seq[dfn[tmp]-Query(1,1,n,dfn[top[tmp]],dfn[tmp]).mx[key]+1];
modify(fa[x],p,v[x]+1);
if (fa[p]) modify(1,1,n,dfn[fa[p]],dfn[fa[p]],Query(1,1,n,dfn[fa[p]])+(key?-1:1));
return Query(1,1,n,1)>=2;
}
}seg;
void work(){
getseq(); seg.clear(); int q,a;
for (read(q);q;--q) read(a),printf("%d\n",seg.modify(a));
}
int main(){
init();
work();
return 0;
}