122 lines
3.6 KiB
C++
122 lines
3.6 KiB
C++
#include <bits/stdc++.h>
|
||
|
||
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<int> 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() {
|
||
//加快读入
|
||
ios::sync_with_stdio(false), cin.tie(0);
|
||
//配置从文本文件读入数据
|
||
freopen("expr.in","r", stdin);
|
||
freopen("expr.out","w", stdout);
|
||
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;
|
||
}
|