题解
2026-08-21 21:52:33
发布于:浙江
1阅读
0回复
0点赞
思路:
后缀表达式 → 表达式树 → 两次 DFS
第一次(后序 / 自底向上):计算每个子树的值 val[u]
第二次(前序 / 自顶向下):计算每个节点的"敏感度" sens[u]
sens[u] = true 表示:若翻转 u 的值,整棵树(根节点)的值会改变
对每个询问(翻转变量 xi):
若 sens[xi对应的叶子节点] = true → 答案 = 1 - 原值
否则 → 答案 = 原值
敏感度传递规则(父节点 p,子节点 c):
若 sens[p] = false,则 sens[c] = false(父都不敏感,子更不敏感)
若 sens[p] = true:
p 是 & 运算:
val[p] = 1 → 两个孩子都是 1,翻转任一个 → 0,两个都敏感
val[p] = 0 →
左=0, 右=0:翻转任一仍为 0,都不敏感
左=0, 右=1:翻转左 → 1(左敏感);翻转右 → 0(右不敏感)
左=1, 右=0:左不敏感,右敏感
p 是 | 运算:
val[p] = 0 → 两个都是 0,翻转任一 → 1,都敏感
val[p] = 1 →
左=1, 右=1:都不敏感
左=1, 右=0:左不敏感,右敏感
左=0, 右=1:左敏感,右不敏感
p 是 ! 运算:
翻转孩子必然翻转父亲,孩子敏感
上代码
#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <sstream>
#include <cctype>
using namespace std;
// 节点类型枚举
const int TYPE_VAR = 0;
const int TYPE_AND = 1; // &
const int TYPE_OR = 2; // |
const int TYPE_NOT = 3; // !
struct Node {
int type;
int left; // 左孩子下标(-1 表示无)
int right; // 右孩子下标(-1 表示无)
int varIdx; // 变量下标(仅叶子节点有效)
bool val; // 子树值
bool sens; // 是否敏感
};
vector<Node> tree;
int varLeaf[100005];
int buildTree(const vector<string>& tokens) {
stack<int> st; // 栈中存节点下标
int id = 0;
for (const string& tok : tokens) {
if (tok == "&" || tok == "|") {
int r = st.top(); st.pop();
int l = st.top(); st.pop();
tree.push_back({tok == "&" ? TYPE_AND : TYPE_OR, l, r, 0, false, false});
st.push(id++);
} else if (tok == "!") {
int c = st.top(); st.pop();
tree.push_back({TYPE_NOT, c, -1, 0, false, false});
st.push(id++);
} else {
int idx = 0;
for (size_t i = 1; i < tok.size(); i++) {
idx = idx * 10 + (tok[i] - '0');
}
tree.push_back({TYPE_VAR, -1, -1, idx, false, false});
varLeaf[idx] = id;
st.push(id++);
}
}
return st.top();
}
void dfsVal(int u) {
Node& node = tree[u];
if (node.type == TYPE_VAR) return;
if (node.type == TYPE_NOT) {
dfsVal(node.left);
node.val = !tree[node.left].val;
} else {
dfsVal(node.left);
dfsVal(node.right);
if (node.type == TYPE_AND)
node.val = tree[node.left].val && tree[node.right].val;
else
node.val = tree[node.left].val || tree[node.right].val;
}
}
void dfsSens(int u) {
Node& node = tree[u];
if (node.type == TYPE_VAR) return;
if (!node.sens) {
if (node.left >= 0) { tree[node.left].sens = false; dfsSens(node.left); }
if (node.right >= 0) { tree[node.right].sens = false; dfsSens(node.right); }
return;
}
if (node.type == TYPE_NOT) {
tree[node.left].sens = true;
dfsSens(node.left);
} else if (node.type == TYPE_AND) {
bool lv = tree[node.left].val;
bool rv = tree[node.right].val;
if (node.val) {
tree[node.left].sens = true;
tree[node.right].sens = true;
} else {
if (!lv && !rv) {
tree[node.left].sens = false;
tree[node.right].sens = false;
} else if (!lv && rv) {
tree[node.left].sens = true;
tree[node.right].sens = false;
} else { // lv && !rv
tree[node.left].sens = false;
tree[node.right].sens = true;
}
}
dfsSens(node.left);
dfsSens(node.right);
} else { // TYPE_OR
bool lv = tree[node.left].val;
bool rv = tree[node.right].val;
if (!node.val) {
tree[node.left].sens = true;
tree[node.right].sens = true;
} else {
if (lv && rv) {
tree[node.left].sens = false;
tree[node.right].sens = false;
} else if (lv && !rv) {
tree[node.left].sens = false;
tree[node.right].sens = true;
tree[node.left].sens = true;
tree[node.right].sens = false;
} else { // !lv && rv
tree[node.left].sens = false;
tree[node.right].sens = true;
}
}
dfsSens(node.left);
dfsSens(node.right);
}
}
int main() {
string s;
getline(cin, s);
vector<string> tokens;
stringstream ss(s);
string tok;
while (ss >> tok) tokens.push_back(tok);
int n;
cin >> n;
vector<int> val(n + 1); // val[1..n]
for (int i = 1; i <= n; i++) cin >> val[i];
tree.reserve(tokens.size());
int root = buildTree(tokens);
for (auto& node : tree) {
if (node.type == TYPE_VAR) {
node.val = val[node.varIdx];
}
}
dfsVal(root);
bool original = tree[root].val;
tree[root].sens = true;
dfsSens(root);
int q;
cin >> q;
while (q--) {
int x;
cin >> x;
int leaf = varLeaf[x];
if (tree[leaf].sens)
cout << (1 - original) << '\n';
else
cout << original << '\n';
}
return 0;
}
这里空空如也







有帮助,赞一个