CF传送门
洛谷传送门
解题思路
注意每个叶子节点的修改是独立的,不会对后面造成影响。
所以我们先从根遍历一边,O(n)求出不改变之前根节点的取值。
然后再从根遍历一遍,求出每个儿子变化会不会对根节点造成影响:
- AND:若另一个儿子是0,则无影响,否则有影响
- OR:若另一个儿子是1,则无影响,否则有影响
- XOR:一定有影响
- NOT:一定有影响
AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=1e6+5;
int n,w[maxn],tp[maxn],v[maxn][2],need[maxn];
string s;
map<string,int> m;
void dfs(int u){
if(tp[u]==0) return;
if(tp[u]==1) dfs(v[u][0]);
else dfs(v[u][0]),dfs(v[u][1]);
if(tp[u]==1) w[u]=!w[v[u][0]];
if(tp[u]==2) w[u]=w[v[u][0]]&w[v[u][1]];
if(tp[u]==3) w[u]=w[v[u][0]]|w[v[u][1]];
if(tp[u]==4) w[u]=w[v[u][0]]^w[v[u][1]];
}
void dfs2(int u){
if(need[u]==0) return;
if(tp[u]==0) return;
if(tp[u]==1) need[v[u][0]]=1;
if(tp[u]==2){
if(w[v[u][0]]==0) need[v[u][1]]=0;
else need[v[u][1]]=1;
if(w[v[u][1]]==0) need[v[u][0]]=0;
else need[v[u][0]]=1;
}
if(tp[u]==3){
if(w[v[u][0]]==0) need[v[u][1]]=1;
else need[v[u][1]]=0;
if(w[v[u][1]]==0) need[v[u][0]]=1;
else need[v[u][0]]=0;
}
if(tp[u]==4){
need[v[u][1]]=need[v[u][0]]=1;
}
dfs2(v[u][0]);
dfs2(v[u][1]);
}
int main(){
ios::sync_with_stdio(false);
cin>>n;
m["IN"]=0;
m["NOT"]=1;
m["AND"]=2;
m["OR"]=3;
m["XOR"]=4;
for(int i=1;i<=n;i++){
cin>>s;
if(s=="IN"){
cin>>w[i];
}else{
if(s=="NOT"){
cin>>v[i][0];
}else{
cin>>v[i][0]>>v[i][1];
}
tp[i]=m[s];
}
}
dfs(1);
need[1]=1;
dfs2(1);
for(int i=1;i<=n;i++){
if(tp[i]==0){
if(need[i]==1) cout<<(!w[1]);
else cout<<w[1];
}
}
return 0;
}