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

88 lines
2.9 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;
const int N = 1000010, M = N << 1;
#define ls e[h[u]]
#define rs e[ne[h[u]]]
int n; // n个变量
int a[N]; // 每个变量对应的数值
char c[N]; // 操作符
stack<int> stk; // 模拟栈
// 链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
// 表示式求值
int dfs(int u) {
if (u <= n) return a[u]; // 如果是叶子,是变量,是数值,返回真实值
if (c[u] == '!')
a[u] = !dfs(ls); //! 只有一个儿子,所以e[h[u]]就是儿子的节点号,对儿子返回的值取反就是当前节点的返回值,同时实现了记忆化
else {
//&和|有两个儿子,分别是e[h[u]]和e[ne[h[u]]]
if (c[u] == '&')
a[u] = dfs(ls) & dfs(rs); // 计算
else
a[u] = dfs(ls) | dfs(rs); // 计算
}
return a[u]; // 返回
}
// https://www.luogu.com.cn/problem/P7073
// 20个测试点,可以过掉6个
int main() {
memset(h, -1, sizeof h); // 初始化链式前向星
string s;
getline(cin, s); // 读整行字符串,带空格的
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i]; // x1,x2,x3的真实值, 0 1 0 0 1
// 数字占了前n个节点,比如x1占用了1号节点,x2占用了2号节点
// n+1开始留给操作符
int idx = n;
for (int i = 0; i < s.size(); i++) {
if (s[i] == ' ') continue; // 放过空格
if (s[i] == 'x') { // 发现是变量标识 x234
int k = 0;
i++;
while (i < s.size() && isdigit(s[i]))
k = k * 10 + s[i++] - '0'; // 取得是 x?,比如?=124
stk.push(k); // x124存到图中,节点号就是124
} else if (s[i] == '!') {
c[++idx] = s[i]; // 记录操作符数组,n+1是第一个操作符对应的树中节点号
add(idx, stk.top()); // 操作符向数字连一条边
stk.pop();
stk.push(idx); // 将操作符也要入栈
} else { // 如果是 & 或 |
c[++idx] = s[i]; // 记录idx号节点是 & 或 | 或 !
int a = stk.top();
stk.pop();
int b = stk.top();
stk.pop();
add(idx, a), add(idx, b); // 1托2建边
stk.push(idx); // 将操作符也要入栈
}
}
// 最后一个入栈的是根,根是一个操作符,叶子都是变量,是数值
int root = stk.top();
int q;
cin >> q;
while (q--) {
int x;
cin >> x;
// 取反
a[x] = !a[x];
// 输出
cout << dfs(root) << endl;
// 还原现场
a[x] = !a[x];
}
return 0;
}