题意:
给出一颗逻辑树,求分别反转每一个输入端的值后,输出端的值。
分析:
额,不得不说这次Div1前面几题真的水。。。打得好累。。。(以前都是悠闲地切题的,这次题水了,为了不掉rating就得疯狂地做。。。)
其实很简单,可以在每个位置维护一个值dpidpi表示ii点值更改后能否影响到根。
转移的条件是,当其父亲 值为1,且当前位置的值反转后,会影响父亲的值,那么当前位置dp值就为1,否则就为0
随便写写就出来了。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 1000010
using namespace std;
int n,k,m,x;
int dp[MAXN];
char s[10];
vector<int> a[MAXN];
int fa[MAXN],bro[MAXN],val[MAXN],re[MAXN];
int ans[MAXN];
void dfs(int x){for(int i=0;i<a[x].size();i++)dfs(a[x][i]);if(re[x]<2){val[x]=re[x];return ;}if(re[x]==2)val[x]=val[a[x][0]]^1;if(re[x]==3)val[x]=val[a[x][0]]&val[a[x][1]];if(re[x]==4)val[x]=val[a[x][0]]|val[a[x][1]];if(re[x]==5)val[x]=val[a[x][0]]^val[a[x][1]];return ;
}
bool check(int x){if(x==1)return 1;if(dp[fa[x]]==0)return 0;int r=re[fa[x]];if(r==2)return 1;int b=bro[x];if(r==3)return (val[fa[x]]!=((val[x]^1)&val[b]));if(r==4)return (val[fa[x]]!=((val[x]^1)|val[b]));if(r==5)return (val[fa[x]]!=((val[x]^1)^val[b]));return 1;
}
void ddp(int x){if(check(x))dp[x]=1;for(int i=0;i<a[x].size();i++)ddp(a[x][i]);
}
int main(){SF("%d",&n);for(int i=1;i<=n;i++){SF("%s",s);int y;if(s[0]=='N'){re[i]=2;SF("%d",&x);a[i].push_back(x);fa[x]=i;}else if(s[0]=='A'){re[i]=3;SF("%d%d",&x,&y);a[i].push_back(x);bro[x]=y;a[i].push_back(y);bro[y]=x;fa[x]=i;fa[y]=i;}else if(s[0]=='O'){re[i]=4;SF("%d%d",&x,&y);a[i].push_back(x);bro[x]=y;a[i].push_back(y);bro[y]=x;fa[x]=i;fa[y]=i;}else if(s[0]=='X'){re[i]=5;SF("%d%d",&x,&y);a[i].push_back(x);bro[x]=y;a[i].push_back(y);bro[y]=x;fa[x]=i;fa[y]=i;}else if(s[0]=='I'){SF("%d",&x);re[i]=x;}}dfs(1);dp[1]=1;ddp(1);for(int i=1;i<=n;i++)if(re[i]<2)PF("%d",dp[i]^val[1]);
}