CodeForces - 339D |
---|
题意: 给定n和m,给你一个包含2^n个数的数组,交替对这些数进行“或操作”和“异或操作”,得到最终的结果。有m次操作,每次操作先将p位置的数修改为v。
题解: 线段树单点修改,唯一特别的是在pushup中返回一个标记,如果上回进行了或操作,这次改为异或。用0和1表示。
从别人哪里学来的骚操作:#define lrt rt << 1
类似这些都会 反复使用,通过#define记为另一种容易写的标识,可以加快写题的速度。
#include<bits/stdc++.h>
using namespace std;
#define lrt rt << 1
#define rrt rt << 1 | 1
#define lson l, m, lrt
#define rson m + 1, r, rrt
const int N = 1 << 17;
int n, q, p, v;
int tree[N << 2];
void pushup(int rt, int flag) {
if(flag) tree[rt] = tree[lrt] ^ tree[rrt];
else tree[rt] = tree[lrt] | tree[rrt];
}
int build(int l, int r, int rt) {
if(l == r) {
cin >> tree[rt];
return 0;
}
int m = (l + r) >> 1;
int flag = build(lson);
build(rson);
pushup(rt, flag);
return flag ^ 1;
}
int update(int p, int val, int l, int r, int rt) {
if(l == r) {
tree[rt] = val;
return 0;
}
int m = (l + r) >> 1;
int flag;
if(p <= m) flag = update(p, v, lson);
else flag = update(p, v, rson);
pushup(rt, flag);
return flag ^ 1;
}
int main() {
ios :: sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> q;
build(1, 1 << n, 1);
while(q--) {
cin >> p >> v;
update(p, v, 1, 1 << n, 1);
cout << tree[1] << endl;
}
return 0;
}