#include using namespace std; const int N = 1000010, M = N << 1; int n; // 变量个数 int w[N]; // 变量参数的值 char c[N]; // 操作符栈 int stk[N], tt; // 数字栈 bool st[N]; // 是不是对 // 邻接表 int e[M], h[N], idx, ne[M]; void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; } // 第一次dfs求原后缀表达式,记录每个节点的计算值 int dfs1(int u) { if (u <= n) return w[u]; // 叶子节点,返回参数值 if (c[u] == '!') // 如果当前节点是运算符!的话,那么,它一定只有一个子节点,节点号:h[u],值:e[h[u]],取反返回即可 w[u] = !dfs1(e[h[u]]); else { // 与和或 int a = e[h[u]], b = e[ne[h[u]]]; // 取当前节点左儿子和右儿子 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] = true; // 因为 if (u <= n) return; // 递归到叶子返回 if (c[u] == '!') { // 取反操作符 dfs2(e[h[u]]); // 前进,继续标记节点 return; } int a = e[h[u]], b = e[ne[h[u]]]; // 左右儿子节点号 if (c[u] == '&') { // &运算 if (w[a]) dfs2(b); // 左儿子=1,对右子树递归标记 if (w[b]) dfs2(a); // 右儿子=1,对左子树递归标记 } else { // |运算 if (!w[a]) dfs2(b); // 左儿子=0,递归右子树,右子树中的某些节点变化会对根造成影响 if (!w[b]) dfs2(a); // 右儿子=0,递归左儿子,左子树中的某些节点变化会对根造成影响 } } int main() { string s; getline(cin, s); cin >> n; // 参数个数 for (int i = 1; i <= n; i++) scanf("%d", &w[i]); // 每个参数对应的数值 memset(h, -1, sizeof h); // 邻接表初始化 // 为了创建一个表达式树,就需要给每个节点创建一个编号。现在已知数字节点,也就是叶子节点数量是n // 所以,运算符的编号就是从++m开始的。 int m = n; // 后缀表达式->栈->建图 // 利用栈进行辅助建图,图才能进行dfs计算 for (int i = 0; i < s.size(); i++) { if (s[i] == ' ') continue; if (s[i] == 'x') { int k = 0; i++; // 跳过x while (i < s.size() && isdigit(s[i])) k = k * 10 + s[i++] - '0'; stk[++tt] = k; } else if (s[i] == '!') { c[++m] = s[i]; //++m这个节点,表达式树中是s[i]这个操作符, /* 表达式树: (1)每个叶子节点的数值 (2)非叶子节点需要记录是什么操作符 记录办法 (1)以树中的节点编号为索引,[1~n]为叶子,[n+1~]为操作符 (2)再开一个数组char c[],记录操作符节点是哪个操作符 */ add(m, stk[tt--]); // 从栈中弹出一个数字,因为是!嘛,树是由上到下的连单向边 stk[++tt] = m; // m节点入栈,方便后续构建 } else { c[++m] = s[i]; add(m, stk[tt--]); // 与!不同,需要由m引向两个节点各一条边 add(m, stk[tt--]); stk[++tt] = m; } } // 计算原式结果 int res = dfs1(m); // 这个m才是根,因为是后缀表达式 // 标记哪些节点影响最终结果 dfs2(m); for (int i = 1; i <= m; i++) { cout << "i=" << i << ",st[" << i << "]=" << st[i] << ",c[" << i << "]=" << c[i] << endl; } int Q; cin >> Q; // 询问个数 while (Q--) { int x; cin >> x; // 修改哪个变量 if (st[x]) // 如果x被打过标记,那么它的变化将会影响根节点的值,对根节点取反即可 printf("%d\n", !res); else // 不会影响根节点的值 printf("%d\n", res); } return 0; }