Codeforces Round #499 (Div. 2) F. Mars rover_dfs_位运算
题解:
首先,我们可以用 在 的时间复杂度求出初始状态每个点的权值。
不难发现,一个叶子节点权值的取反会导致根节点的权值取反当且仅当从该叶子节点到根节点这一条链上的每个点的权值都被取反(都被影响到)。而这4种逻辑运算中, 和 是最简单的,即只要2个儿子中的一个儿子的值被取反,该点的值就会被取反。但 和 存在只修改一个儿子时不会对该点的权值产生影响的情况,这就需要我们进行一下特判。
我们给每个节点开一个 变量, = 的话说明该节点不会随这儿子节点权值的变化而变化, 则相反。如果一个节点的 , 那么就没有必要进行特判,直接将所有子节点的 设成 即可。
反之,则对左右儿子进行特判,分别下传标记即可。
Code:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1002000 + 3;
int n, ans[maxn], node[maxn], ch[maxn][2], val[maxn];
bool lazy[maxn];
inline int get(char str[]){
if(str[0] == 'I') return 1;
if(str[0] == 'N') return 2;
if(str[0] == 'O') return 3;
if(str[0] == 'A') return 4;
if(str[0] == 'X') return 5;
}
int dfs1(int u)
{
if(node[u] == 1) return val[u] ;
if(node[u] == 2) return (val[u] = !dfs1(ch[u][0]) );
if(node[u] == 3) return (val[u] = (dfs1(ch[u][0]) | dfs1(ch[u][1])) );
if(node[u] == 4) return (val[u] = (dfs1(ch[u][0]) & dfs1(ch[u][1])) );
if(node[u] == 5) return (val[u] = (dfs1(ch[u][0]) ^ dfs1(ch[u][1])) );
}
void dfs2(int u)
{
if(lazy[u] == false) { lazy[ch[u][0]] = lazy[ch[u][1]] = false;}
else{
switch(node[u])
{
case 2:
lazy[ch[u][0]] = true;
break;
case 3:
if(val[ch[u][0]])
lazy[ch[u][1]] = false;
else
lazy[ch[u][1]] = true;
if(val[ch[u][1]])
lazy[ch[u][0]] = false;
else
lazy[ch[u][0]] = true;
break;
case 4:
if(!val[ch[u][0]])
lazy[ch[u][1]] = false;
else
lazy[ch[u][1]] = true;
if(!val[ch[u][1]])
lazy[ch[u][0]] = false;
else
lazy[ch[u][0]] = true;
break;
case 5:
lazy[ch[u][0]] = lazy[ch[u][1]] = true;
break;
}
}
lazy[0] = 0;
if(ch[u][0]) dfs2(ch[u][0]);
if(ch[u][1]) dfs2(ch[u][1]);
}
int main()
{
memset(lazy, 1, sizeof(lazy));
scanf("%d",&n);
for(int i = 1;i <= n; ++i)
{
char str[10];
scanf("%s",str);
node[i] = get(str);
if(node[i] == 1)
scanf("%d",&val[i]);
else if(node[i] == 2)
scanf("%d",&ch[i][0]);
else
scanf("%d%d",&ch[i][0],&ch[i][1]);
}
dfs1(1);
lazy[1] = true;
dfs2(1);
for(int i = 1;i <= n; ++i)
if(node[i] == 1) printf("%d",val[1] ^ lazy[i]);
printf("\n");
return 0;
}