You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
2.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}