原题走这里
首先我们定义节点的状态0,1,2,3分别代表该节点分别接收到0,1,2,3个信号。
那么我们会发现,叶子节点的状态改变,会导致叶子节点到根的路径上一连串节点的状态改变。
比如当某叶子节点到根的路径上,
由叶子节点开始的若干个连续的节点均处于状态2,且该叶子节点处于激活状态,
那么此时,如果我们改变这一叶子节点的状态,
则从叶子节点开始,一路向根走,遇到的这些连续的2节点全部会变成状态1,
此外还要对应更新最后一个2节点的父节点。
因此,我们实质上就是要实现以下操作(单点修改之类的就不算了):
1.查询从根到某叶节点有多少个从叶节点开始的连续的1节点或2节点
2.把这些节点变成状态1或2
恩,于是我们可以树链剖分,用线段树维护本区间最右节点的状态,以及从本区间右端点开始有多少个连续的状态1或状态2节点即可。
具体细节见代码如下:
为什么我的代码这么慢啊
#include
using namespace std;
char buf[25000000],*pp=buf;
#define getchar() *(pp++)
inline int read() {
int X=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')w=(ch=='-'?-1:1),ch=getchar();
while(ch>='0'&&ch<='9')X=X*10+ch-'0',ch=getchar();
return X*w;
}
struct edge {
int v,p;
inline edge(int _v=0,int _p=0) {
v=_v;
p=_p;
}
} e[3000010];
int n,q,head[1500010],top,sr[6000010],siz[1500010],dep[1500010],w[1500010],tp[1500010],f[1500010],son[1500010],m,s[1500010],st[6000010],lazy[6000010];
inline void addedge(int u,int v) {
e[++top]=edge(v,head[u]);
head[u]=top;
e[++top]=edge(u,head[v]);
head[v]=top;
}
void dfs1(int u,int fa) {
siz[u]=1;
f[u]=fa;
for(int i=head[u]; i; i=e[i].p) {
int v=e[i].v;
if(v==fa)continue;
dep[e[i].v]=dep[u]+1;
dfs1(v,u);
siz[u]+=siz[v];
f[v]=u;
if(siz[son[u]]void dfs2(int u,int t) {
w[u]=++m;
tp[u]=t;
if(son[u])dfs2(son[u],t);
for(int i=head[u]; i; i=e[i].p) {
int v=e[i].v;
if(v==f[u]||v==son[u])continue;
dfs2(v,v);
}
}
int dfs3(int u) {
if(s[w[u]]>=0)return s[w[u]];
int ret=-1;
for(int i=head[u]; i; i=e[i].p) {
int v=e[i].v;
if(v==f[u])continue;
ret+=dfs3(v)>0;
}
return s[w[u]]=ret;
}
inline void push_down(int k,int l,int r) {
if(l!=r&&lazy[k]>=0) {
int mid=(l+r)>>1;
lazy[k<<1]=lazy[k<<1|1]=lazy[k];
sr[k<<1]=mid-l+1;
sr[k<<1|1]=r-mid;
st[k<<1]=st[k<<1|1]=lazy[k];
}
lazy[k]=-1;
}
inline void update(int k,int l,int r) {
int mid=(l+r)>>1;
st[k]=st[k<<1|1];
if(st[k]==0||st[k]==1) {
sr[k]=sr[k<<1|1];
if(sr[k]==r-mid&&st[k]==st[k<<1]) {
sr[k]+=sr[k<<1];
}
} else {
sr[k]=0;
}
}
void build(int k,int l,int r) {
if(l==r) {
st[k]=s[l];
if(s[l]==0||s[l]==1)sr[k]=1;
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
update(k,l,r);
}
int query(int x) {
int k=1;
for(int l=1,r=m;l^r;)
{
push_down(k,l,r);
int mid=(l+r)>>1;
if(x<=mid)k=(k<<1),r=mid;
else k=(k<<1|1),l=mid+1;
}
return st[k];
}
int ask(int k,int l,int r,int L,int R,bool x) {
push_down(k,l,r);
if(L==l&&r==R) {
return st[k]==x?sr[k]:0;
}
int mid=(l+r)>>1,r1,r2;
if(R<=mid) {
return ask(k<<1,l,mid,L,R,x);
} else if(L>mid) {
return ask(k<<1|1,mid+1,r,L,R,x);
} else {
r2=ask(k<<1|1,mid+1,r,mid+1,R,x);
r1=ask(k<<1,l,mid,L,mid,x);
return r2==(R-mid)?r2+r1:r2;
}
}
void work(int k,int l,int r,int L,int R,int x) {
push_down(k,l,r);
if(L<=l&&r<=R) {
lazy[k]=x;
sr[k]=r-l+1;
st[k]=x;
return;
}
int mid=(l+r)>>1;
if(L<=mid) {
work(k<<1,l,mid,L,R,x);
}
if(R>mid) {
work(k<<1|1,mid+1,r,L,R,x);
}
update(k,l,r);
}
void work(int k,int l,int r,int x,bool y) {
push_down(k,l,r);
if(l==r) {
st[k]+=y?1:-1;
sr[k]=(st[k]==0||st[k]==1);
return;
}
int mid=(l+r)>>1;
if(x<=mid) {
work(k<<1,l,mid,x,y);
} else {
work(k<<1|1,mid+1,r,x,y);
}
update(k,l,r);
}
void change(int x,bool y) {
for(register int t; x; x=f[tp[x]]) {
t=ask(1,1,m,w[tp[x]],w[x],y^1);
if(!t) {
work(1,1,m,w[x],y);
break;
}
work(1,1,m,w[x]-t+1,w[x],y);
if(t<=w[x]-w[tp[x]])
{
work(1,1,m,w[x]-t,y);
break;
}
}
}
int main() {
fread(buf,sizeof(char),sizeof(buf),stdin);
memset(lazy,-1,sizeof(lazy));
memset(s,-1,sizeof(s));
n=read();
for(int i=1; i<=n; i++) {
for(int j=1; j<=3; j++) {
addedge(i,read());
}
}
dfs1(1,0);
dfs2(1,1);
for(int i=n+1; i<=3*n+1; i++) {
s[w[i]]=read();
}
dfs3(1);
build(1,1,m);
q=read();
for(int i=1,x,y; i<=q; i++) {
x=read();
y=query(w[x]);
change(x,y^1);
putchar((int)(query(1)>0)+'0');
putchar('\n');
}
return 0;
}