SB题,刚开始还以为要写倍增,写到一半发现是个SB递推题
由于每次只改变一个叶节点的状态,因此我们可以先扫出来每个点的值
设(f_{x,0/1})表示当(x)的点取值为(0/1)时,根节点的值是多少
转移很显然,直接看代码,复杂度(O(n))
#include<cstdio>
#define RI register int
#define CI const int&
using namespace std;
const int N=1000005;
int n,head[N],cnt,fa[N],son[N][2],val[N],f[N][2],x,c[N]; char opt[10]; //0/1: Leaf; 2:And; 3:Or; 4:Xor; 5:Not
inline int work(CI now)
{
switch (c[now])
{
case 2: return val[son[now][0]]&val[son[now][1]];
case 3: return val[son[now][0]]|val[son[now][1]];
case 4: return val[son[now][0]]^val[son[now][1]];
case 5: return !val[son[now][0]];
}
}
inline void DFS1(CI now=1)
{
if (!now||c[now]<=1) return; DFS1(son[now][0]); DFS1(son[now][1]); val[now]=work(now);
}
inline void DFS2(CI now=1)
{
if (!now) return; int tp=val[now]; if (now!=1)
{
val[now]=0; f[now][0]=f[fa[now]][work(fa[now])];
val[now]=1; f[now][1]=f[fa[now]][work(fa[now])];
}
val[now]=tp ;DFS2(son[now][0]); DFS2(son[now][1]);
}
int main()
{
RI i; for (scanf("%d",&n),i=1;i<=n;++i)
{
scanf("%s",opt+1); if (opt[1]=='I'||opt[1]=='N')
{
if (scanf("%d",&x),opt[1]=='I') c[i]=val[i]=x; else c[i]=5,son[i][0]=x,fa[x]=i;
}
else
{
scanf("%d",&x); son[i][0]=x; fa[x]=i; scanf("%d",&x); son[i][1]=x; fa[x]=i;
if (opt[1]=='A') c[i]=2; else if (opt[1]=='O') c[i]=3; else c[i]=4;
}
}
for (DFS1(),f[1][1]=1,DFS2(),i=1;i<=n;++i) if (c[i]<=1) printf("%d",f[i][c[i]^1]);
return 0;
}