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.

93 lines
3.0 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int e[N], el; // 表达式数组
int w[N];
int stk[N], tt;
/*
630
1
2
*/
// 计算表达式的值
int calc() {
// 后缀表达式求值,需要借助栈
tt = 0;
// 枚举所有的表达式符号
for (int i = 1; i <= el; i++) {
// 如果是数字,直接入栈
if (e[i] > 0) stk[++tt] = w[e[i]]; // e[i]=1 --> 1 --> x1---> w[1] <==> w[e[i]]
// 如果是 非 操作符取一个数字出来 运算
else if (e[i] == -3) { //! 非 运算符
int n1 = stk[tt--];
stk[++tt] = !n1; // 对n1取反再放回去
} else {
// 如果是与和或的话,那么需要取两个操作符
// 注意一个细节这里从栈中取出的数字是反的n1是后面的n2是前面的
int n1 = stk[tt--];
int n2 = stk[tt--];
// 根据e[i]的操作符不同,知道是与还是或
if (e[i] == -1)
stk[++tt] = n2 & n1;
else
stk[++tt] = n2 | n1;
}
}
return stk[tt];
}
int main() {
// 文件输入
// freopen("3.in", "r", stdin);
// 读入整行
string s;
getline(cin, s); // 带空格的整行数据
// 拆开
for (int i = 0; i < s.size(); i++) {
if (s[i] == ' ') continue; // 跳过空格
if (s[i] == 'x') {
i++; // 跳过x
int k = 0;
while (i < s.size() && s[i] >= '0' && s[i] <= '9') k = k * 10 + s[i++] - '0';
e[++el] = k; // 记录操作符 x1,x2,...,x332
}
// 因为e[]中需要区分是操作符变量不能直接使用ASCII因为比如 ascii(&)=38,可是人家k=38,也就是有x38这个变量存在你就无法分清楚是&还是x38
// 使用负数-1-2-3进行标识就不存在这个问题肯定能唯一标识是操作符还是操作数
else if (s[i] == '&')
e[++el] = -1;
else if (s[i] == '|')
e[++el] = -2;
else if (s[i] == '!')
e[++el] = -3;
}
// 打印表达式里面的值,看看有没有什么错误,单元测试
// for (int i = 1; i <= len; i++) cout << e[i] << " ";
// 读入n个变量
// 上面取入的是x1,x2,x3也就是变量的下标读入的是真正的操作数值
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> w[i];
// Q次查询
int Q, x;
cin >> Q;
for (int i = 1; i <= Q; i++) {
// 对第x个操作数进行取反
cin >> x;
// 只时临时修改,不是永久修改
w[x] = !w[x];
// 重新计算表达式的值
printf("%d\n", calc());
// 还回来
w[x] = !w[x];
}
return 0;
}