1 条题解
-
0
#include #include #include #include #include #include #include #include using namespace std; const int N=1000010; int n,m,h[N],e[N],ne[N],idx,w[N];//n是叶节点数量,m是结点总数量 bool st[N];//标记某节点是否会影响答案 char c[N];//存每个节点符号,下标从n开始,1~n不存是为了方便表示叶节点 stack stk;//存每个节点的编号 inline void c_plus(){//提速 ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } inline void init(){//预处理链式前向星 memset(h,-1,sizeof(h)); idx=0; } inline void add(int a,int b){//链式前向星,添加一条边a->b e[idx]=b; ne[idx]=h[a]; h[a]=idx++; } int dfs1(int u){//求原表达式的值,u为当前节点编号 if (!c[u]){//如果该位置无符号(即如果是叶节点) return w[u];//直接返回其权值 }else if (c[u]'!'){//如果是非运算 w[u]=!dfs1(e[h[u]]);//w[u]=将u递归求值后取反的值 }else{//处理二元运算符 int a=e[h[u]],b=e[ne[h[u]]];//a为左子节点,b为右子节点 if (c[u]'&'){//如果是与运算 w[u]=dfs1(a)&dfs1(b);//同理,不解释了 }else{//如果是或运算 w[u]=dfs1(a)|dfs1(b); } } return w[u]; } void dfs2(int u){//标记哪些节点会影响答案 st[u]=1; if (!c[u]){//如果该位置无符号(即如果是叶节点) return;//无法继续下去 }else if (c[u]'!'){//如果是非运算 dfs2(e[h[u]]);//分析中已解释 }else{//处理二元运算符 int a=e[h[u]],b=e[ne[h[u]]];//a为其左子节点,b为右子节点 if (c[u]'&'){//如果是与运算 if (w[a]){//分析中已解释 dfs2(b); } if (w[b]){//分析中已解释 dfs2(a); } }else{//如果是或运算 if (!w[a]){//分析中已解释 dfs2(b); } if (!w[b]){//分析中已解释 dfs2(a); } } } } int main(){ c_plus(); init(); string s; getline(cin,s);//因为字符串中有空格,所以用getline cin>>n; for (int i=1;i<=n;i++){ cin>>w[i]; } m=n;//m=n+非叶节点数量,所以让m先等于n,再加上非叶节点数量 for (int i=0;i<s.size();i++){ if (s[i]' '){ continue; }else if (s[i]'x'){//求出节点编号 int j=i+1,x=0; while (j<s.size() && isdigit(s[j])){//双指针算法求整个数字 x=x*10+s[j++]-'0'; } stk.push(x);//将该数字存入栈 i=j;//注意不是i=j-1,毕竟由题意此时j表示的是空格 }else if (s[i]=='!'){//如果是非运算 c[++m]=s[i]; add(m,stk.top());//表示'!'的子节点是栈顶元素 stk.pop(); stk.push(m);//将当前子节点编号放进栈 }else{//处理二元运算符'&'和'|' c[++m]=s[i]; add(m,stk.top()); stk.pop(); add(m,stk.top()); stk.pop(); stk.push(m); } } int ans=dfs1(m); dfs2(m); int q,x; cin>>q; while (q--){ cin>>x; if (st[x]){//若该节点会影响答案 cout<<(ans^1)<<endl;//直接取反,因为答案不是0就是1 }else{ cout<<ans<<endl;//正常输出 } } return 0; }
信息
- ID
- 296
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 30
- 已通过
- 15
- 上传者