Files
python/TangDou/CSP-J/J2_2020/3_Tree_2.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

113 lines
3.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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() {
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;
}