题目链接:https://vjudge.net/problem/FZU-2105
其实我想放银川网络赛的链接,emmm
题解:首先或和与是能相互掩盖的,因此我们就可以把这两者用一个laz标记,laz=1表示区间都变为1,laz=-1表示区间都为0,有兴趣可以做一下这个题:https://blog.csdn.net/mmk27_word/article/details/90716575,而这个题又加上了异或,那么如果这个区间有laz标记,也就是说都要变为0或1,那么一异或就要反转一下,此时异或只要把当前的laz反转即可,如果没有laz标记,那么就要lz标记一下异或操作,或和与对也是对异或起到遮盖作用的
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
struct node {
int l, r;
int laz[4];
int lz[4];
int len;
int num[4];
}tree[N << 2];
int n, m;
int a[N];
void pushup(int cur) {
for(int i = 0; i < 4; i++) {
tree[cur].num[i] = tree[cur << 1].num[i] + tree[cur << 1 | 1].num[i];
}
}
void build(int l, int r, int cur) {
tree[cur].l = l;
tree[cur].r = r;
tree[cur].len = r - l + 1;
for(int i = 0; i < 4; i++ ) {
tree[cur].laz[i] = 0;
tree[cur].num[i] = 0;
tree[cur].lz[i] = 0;
}
if(l == r) {
for(int i = 0; i < 4; i++) {
if((a[l] >> i) & 1) {
tree[cur].num[i] = 1;
}
}
return;
}
int mid = (l + r) >> 1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
pushup(cur);
}
void pushdown(int cur) {
for(int i=0;i<4;i++)
{
if(tree[cur].laz[i]==1)
{
tree[cur<<1].num[i]=tree[cur<<1].len;
tree[cur<<1].laz[i]=1;
tree[cur<<1].lz[i]=0;
tree[cur<<1|1].num[i]=tree[cur<<1|1].len;
tree[cur<<1|1].laz[i]=1;
tree[cur<<1|1].lz[i]=0;
tree[cur].laz[i]=0;
}
if(tree[cur].laz[i]==-1)
{
tree[cur<<1].num[i]=0;
tree[cur<<1].laz[i]=-1;
tree[cur<<1].lz[i]=0;
tree[cur<<1|1].num[i]=0;
tree[cur<<1|1].laz[i]=-1;
tree[cur<<1|1].lz[i]=0;
tree[cur].laz[i]=0;
}
if(tree[cur].lz[i]) {
tree[cur<<1].lz[i] ^= 1;
tree[cur<<1].num[i]=tree[cur<<1].len-tree[cur<<1].num[i];
if(tree[cur << 1].laz[i]) {
if(tree[cur << 1].laz[i] == 1) {
tree[cur<<1].laz[i]=-1;
tree[cur<<1].lz[i]=0;
} else if(tree[cur << 1].laz[i] == -1){
tree[cur<<1].laz[i]=1;
tree[cur<<1].lz[i]=0;
}
}
tree[cur<<1|1].lz[i] ^= 1;
tree[cur<<1|1].num[i]=tree[cur<<1|1].len-tree[cur<<1|1].num[i];
if(tree[cur << 1 | 1].laz[i]) {
if(tree[cur << 1 | 1].laz[i] == 1) {
tree[cur<<1|1].laz[i]=-1;
tree[cur<<1|1].lz[i] = 0;
} else if(tree[cur<<1|1].laz[i] == -1){
tree[cur<<1|1].laz[i]=1;
tree[cur<<1|1].lz[i] = 0;
}
}
tree[cur].lz[i] = 0;
}
}
}
void update(int pl,int pr,int cur,int op,int v)
{
if(pl<=tree[cur].l && tree[cur].r<=pr)
{
if(op==1)
{
for(int i=0;i<4;i++)
{
if((1<<i) & v)
{
tree[cur].num[i]=tree[cur].len;
tree[cur].laz[i]=1;
tree[cur].lz[i]=0;
}
}
}
else if(op == 2)
{
for(int i=0;i<4;i++)
{
if(!((1<<i) & v))
{
tree[cur].num[i]=0;
tree[cur].laz[i]=-1;
tree[cur].lz[i]=0;
}
}
} else {
for(int i = 0; i< 4; i++) {
if((1<<i)&v) {
tree[cur].num[i] = tree[cur].len - tree[cur].num[i];
tree[cur].lz[i] ^= 1;
if(tree[cur].laz[i] == 1) {
tree[cur].laz[i] = -1;
tree[cur].lz[i] = 0;
}
else if(tree[cur].laz[i] == -1) {
tree[cur].laz[i] = 1;
tree[cur].lz[i] = 0;
}
}
}
}
return;
}
pushdown(cur);
if(pl<=tree[cur<<1].r) update(pl,pr,cur<<1,op,v);
if(pr>=tree[cur<<1|1].l) update(pl,pr,cur<<1|1,op,v);
pushup(cur);
}
int query(int pl, int pr, int cur) {
int res = 0;
if(pl <= tree[cur].l && tree[cur].r <= pr) {
for(int i = 0; i < 4; i++) {
res += (1 << i) * tree[cur].num[i];
}
return res;
}
pushdown(cur);
if(pl <= tree[cur << 1].r) res += query(pl, pr, cur << 1);
if(pr >= tree[cur << 1 | 1].l) res += query(pl, pr, cur << 1 | 1);
pushup(cur);
return res;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
build(1, n, 1);
char op[10];
int l, r, x;
while(m--) {
scanf("%s", op);
if(op[0] == 'S') {
scanf("%d %d", &l, &r);l++, r++;
printf("%d\n", query(l, r, 1));
} else if(op[0] == 'X' ) {
scanf("%d %d %d", &x, &l, &r);l++, r++;
update(l, r, 1, 3, x);
} else if(op[0] == 'O') {
scanf("%d %d %d", &x, &l, &r);l++, r++;
update(l, r, 1, 1, x);
} else {
scanf("%d %d %d", &x, &l, &r);l++, r++;
update(l, r, 1, 2, x);
}
}
}
return 0;
}
/*
5 90
1 1 1 1 1
SUM 0 4
XOR 2 0 1
SUM 0 1
OR 2 0 1
SUM 0 1
YU 2 0 1
SUM 0 1
XOR 5 0 4
SUM 1 3
*/