http://acm.fzu.edu.cn/problem.php?pid=2105
这个是有点东西,分解位操作之后要考虑lazy的影响,假如不顾一切往下PushDown的话要先判断叶子,叶子是不能PushDown的。其次要Build的时候清空lazy。不顾一切先PushDown并不能改变运算符优先级的影响,因为子树也可能有lazy标记。所以当时银川重赛弄的那个是白弄的。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e6;
const int MAXLOGAI = 4;
int a[MAXN + 5];
int st[MAXN * 4 + 5][MAXLOGAI];
char lazy[MAXN * 4 + 5][MAXLOGAI];
inline void PushUp(int o) {
for(int id = 0; id < MAXLOGAI; ++id)
st[o][id] = st[o << 1][id] + st[o << 1 | 1][id];
}
inline void PushDown(int o, int l, int r) {
for(int id = 0; id < MAXLOGAI; ++id) {
if(lazy[o][id]) {
int mid = l + r >> 1;
if(lazy[o][id] == 1) {
if(lazy[o << 1][id] == 0) {
st[o << 1][id] = (mid - l + 1) - st[o << 1][id];
lazy[o << 1][id] = 1;
} else if(lazy[o << 1][id] == 1) {
st[o << 1][id] = (mid - l + 1) - st[o << 1][id];
lazy[o << 1][id] = 0;
} else if(lazy[o << 1][id] == 2) {
st[o << 1][id] = 0;
lazy[o << 1][id] = 3;
} else if(lazy[o << 1][id] == 3) {
st[o << 1][id] = (mid - l + 1);
lazy[o << 1][id] = 2;
}
if(lazy[o << 1 | 1][id] == 0) {
st[o << 1 | 1][id] = (r - (mid + 1) + 1) - st[o << 1 | 1][id];
lazy[o << 1 | 1][id] = 1;
} else if(lazy[o << 1 | 1][id] == 1) {
st[o << 1 | 1][id] = (r - (mid + 1) + 1) - st[o << 1 | 1][id];
lazy[o << 1 | 1][id] = 0;
} else if(lazy[o << 1 | 1][id] == 2) {
st[o << 1 | 1][id] = 0;
lazy[o << 1 | 1][id] = 3;
} else if(lazy[o << 1 | 1][id] == 3) {
st[o << 1 | 1][id] = (r - (mid + 1) + 1);
lazy[o << 1 | 1][id] = 2;
}
} else if(lazy[o][id] == 2) {
st[o << 1][id] = (mid - l + 1);
lazy[o << 1][id] = 2;
st[o << 1 | 1][id] = (r - (mid + 1) + 1);
lazy[o << 1 | 1][id] = 2;
} else {
st[o << 1][id] = 0;
lazy[o << 1][id] = 3;
st[o << 1 | 1][id] = 0;
lazy[o << 1 | 1][id] = 3;
}
lazy[o][id] = 0;
}
}
}
void Build(int o, int l, int r) {
for(int id = 0; id < MAXLOGAI; ++id)
lazy[o][id] = 0;
if(l == r) {
for(int id = 0; id < MAXLOGAI; ++id)
st[o][id] = (a[l] & (1 << id)) ? 1 : 0;
} else {
int mid = l + r >> 1;
Build(o << 1, l, mid);
Build(o << 1 | 1, mid + 1, r);
PushUp(o);
}
}
void Update(int o, int l, int r, int ql, int qr, int op, int x) {
//op=1 ^
//op=2 |
//op=3 &
if(l != r)
PushDown(o, l, r);
if(ql <= l && r <= qr) {
if(op == 1) {
for(int id = 0; id < MAXLOGAI; ++id) {
if(x & (1 << id)) {
st[o][id] = (r - l + 1) - st[o][id];
lazy[o][id] = op;
}
}
} else if(op == 2) {
for(int id = 0; id < MAXLOGAI; ++id) {
if(x & (1 << id)) {
st[o][id] = (r - l + 1);
lazy[o][id] = op;
}
}
} else {
for(int id = 0; id < MAXLOGAI; ++id) {
if(!(x & (1 << id))) {
st[o][id] = 0;
lazy[o][id] = op;
}
}
}
} else {
int mid = l + r >> 1;
if(ql <= mid)
Update(o << 1, l, mid, ql, qr, op, x);
if(qr >= mid + 1)
Update(o << 1 | 1, mid + 1, r, ql, qr, op, x);
PushUp(o);
}
}
ll Query(int o, int l, int r, int ql, int qr) {
if(l != r)
PushDown(o, l, r);
if(ql <= l && r <= qr) {
ll res = 0;
for(int id = 0; id < MAXLOGAI; ++id)
res += 1ll * (1 << id) * (st[o][id]);
return res;
} else {
ll res = 0;
int mid = l + r >> 1;
if(ql <= mid)
res += Query(o << 1, l, mid, ql, qr);
if(qr >= mid + 1)
res += Query(o << 1 | 1, mid + 1, r, ql, qr);
return res;
}
}
int main() {
#ifdef localll
freopen("lyz.in", "r", stdin);
#endif // local
int T, n, m;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
Build(1, 1, n);
for(int i = 1; i <= m; ++i) {
char ops[10];
int l, r, x;
scanf("%s", ops);
if(ops[0] == 'S') {
scanf("%d%d", &l, &r);
++l, ++r;
printf("%lld\n", Query(1, 1, n, l, r));
} else {
scanf("%d%d%d", &x, &l, &r);
++l, ++r;
if(ops[0] == 'X') {
Update(1, 1, n, l, r, 1, x);
} else if(ops[0] == 'O') {
Update(1, 1, n, l, r, 2, x);
} else if(ops[0] == 'A') {
Update(1, 1, n, l, r, 3, x);
}
}
}
}
}