CF1010D Mars rover

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;
}
posted @ 2020-08-20 10:00  空気力学の詩  阅读(206)  评论(0编辑  收藏  举报