#include using namespace std; // 重定义左右儿子 #define ls e[h[u]] #define rs e[ne[h[u]]] const int N = 1000010, M = N << 1; int n; int a[N]; // 每个变量的数值,0或1 char c[N]; // 记录 c[i]是哪种操作符,比如 & | !,如果是变量x1,x2,x3 ... 节点,则默认值是0 stack stk; // 建立表示树用到的栈 // 邻接表 int e[M], h[N], idx, ne[M]; void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; } // 逻辑表达式求值计算 int dfs1(int u) { if (u <= n) return a[u]; if (c[u] == '!') a[u] = !dfs1(ls); else { if (c[u] == '&') a[u] = dfs1(ls) & dfs1(rs); else if (c[u] == '|') a[u] = dfs1(ls) | dfs1(rs); } return a[u]; } // 标记以u为根的子树,每个数值结点(叶子结点)变更,是否对整体结果有影响,true:有影响,false:无影响 int st[N]; void dfs2(int u) { if (u <= n) { // 叶子节点 st[u] = 1; // 这个叶子节点的修改,对整体结果有影响。如果无法到达这个位置,就表示无影响 return; } if (c[u] == '!') // 非运算符,左儿子的变化会影响结果 dfs2(ls); else { if (c[u] == '&') { // ① 如果左儿子是1,右儿子会影响结果 // ② 如果右儿子是1,左儿子会影响结果 if (a[ls]) dfs2(rs); if (a[rs]) dfs2(ls); } else if (c[u] == '|') { // ③ 如果左儿子是0,右儿子会影响结果 // ④ 如果右儿子是0,左儿子会影响结果 if (!a[ls]) dfs2(rs); if (!a[rs]) dfs2(ls); } } } int main() { string s; getline(cin, s); cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; // 初始化 memset(h, -1, sizeof h); // 放过前n个,从n+1开始 int idx = n; for (int i = 0; i < s.size(); i++) { if (s[i] == ' ') continue; if (s[i] == 'x') { int k = 0; i++; while (i < s.size() && isdigit(s[i])) k = k * 10 + s[i++] - '0'; stk.push(k); } else if (s[i] == '!') { c[++idx] = s[i]; add(idx, stk.top()); stk.pop(); stk.push(idx); } else { c[++idx] = s[i]; int x = stk.top(); stk.pop(); int y = stk.top(); stk.pop(); add(idx, x), add(idx, y); stk.push(idx); } } int root = stk.top(); // 计算初始值,因为后面的修改,可能不改变原始值,也可能改变原始值 // 首先我们要计算出每个操作符所在位置的原始结果值 int res = dfs1(root); // 标记每个数值结点(叶子结点)变更,是否对整体结果有影响,true:有影响,false:无影响 dfs2(root); // 处理q次询问 int q; cin >> q; // 询问时查表即可,整个程序的时间复杂度为O(q) while (q--) { int x; cin >> x; if (st[x]) // 如果x被打过标记,那么它的变化将会影响根节点的值,对根节点异或1即可 printf("%d\n", res ^ 1); else // 不会影响根节点的值 printf("%d\n", res); } return 0; }