这种形式的题还是不熟悉。
对于十进制数的异或运算不满足分配率,因而无法直接记录区间和。
记录[l, r]区间各个二进制位上1的数目,而各个二进制位上1的数目小于或等于r - l + 1(由于ai<10000000 < 1<<20 = 1048576,可以记录20个位就行了);
异或运算满足结合率,因而可延迟标记要异或的数。
最后把二进制转换成十进制就行了,会暴int。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <map>
#include <iostream>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
const int maxn = 100010;
struct Tree
{
int dig[22];
}tree[maxn<<2];
int lazy[maxn<<2];
void PushUp(int rt)
{
for(int i= 0; i < 22; i++)
{
tree[rt].dig[i] = tree[rt<<1].dig[i] + tree[rt << 1|1].dig[i];
}
}
void PushDown(int rt, int l, int r)
{
if(lazy[rt] == 0) return;
lazy[rt<<1] ^= lazy[rt];
lazy[rt<<1|1] ^= lazy[rt];
int m = (l + r) >> 1;
for(int i = 0; i < 22; i++)
{
int d = 1 << i;
if(lazy[rt] & d)
{
tree[rt << 1].dig[i] = m - l + 1 - tree[rt << 1].dig[i];
tree[rt << 1|1].dig[i] = r - m - tree[rt << 1|1].dig[i];
}
}
lazy[rt] = 0;
}
void Build(int l, int r, int rt)
{
lazy[rt] = 0;
if(l == r)
{
int a;
cin >> a;
for(int i = 0; i < 22; i++)
{
if(a & 1 << i)
tree[rt].dig[i] = 1;
else
tree[rt].dig[i] = 0;
}
return;
}
int m = (l + r) >> 1;
Build(lson);
Build(rson);
PushUp(rt);
}
void Update(int l, int r, int rt, int L, int R, int x)
{
if(L <= l && r <= R)
{
lazy[rt] ^= x;
for(int i = 0; i < 22; i++)
{
if(x & (1 << i))
{
tree[rt].dig[i] = r - l + 1 - tree[rt].dig[i];
}
}
return ;
}
PushDown(rt, l, r);
int m = (l + r) >> 1;
if(L <= m)
Update(lson, L, R, x);
if(m < R)
Update(rson, L, R, x);
PushUp(rt);
}
long long Query(int l, int r, int rt, int L, int R)
{
long long ret = 0;
if(L <= l && r <= R)
{
for(int i = 0; i < 22; i++)
{
ret = ret + (long long)tree[rt].dig[i] * (1 << i);
}
return ret;
}
PushDown(rt, l, r);
int m = (l + r) >> 1;
if(L <= m)
ret += Query(lson, L, R);
if(m < R)
ret += Query(rson, L, R);
PushUp(rt);
return ret;
}
int main()
{
int n;
while(cin>>n)
{
Build(1, n, 1);
int m;
cin >> m;
while(m--)
{
int cmd, l, r, x;
cin >> cmd;
if(cmd == 1)
{
cin >> l >> r;
cout << Query(1, n, 1, l, r) << endl;
}
else
{
cin >> l >> r >> x;
Update(1, n, 1, l, r, x);
}
}
}
return 0;
}