Song Zha Zha has an 11-indexed array A . Li Zha Zha has QQ queries . Each query has two integers LL, RR , asking Ran Zha Zha to do the following thing .First , find all subintervals of [L,R][L,R] . Then calculate their xor sum . For example .
A={1,2,3}A=1,2,3 , L=1L=1, R=3R=3.
All subintervals of [1,3][1,3] are [1,1],[2,2],[3,3],[1,2],[2,3],[3,3][1,1],[2,2],[3,3],[1,2],[2,3],[3,3] .Their xor sum = 1 + 2 + 3 + 11+2+3+1 xor 2 + 22+2xor 3 + 13+1 xor 22 xor 33 .
Xor means exclusive or . (^
in C++ or Java )
Input
The input contains multiple test cases.
First line contains an integer TT (1 \le T \le 10)(1≤T≤10) , which is the number of test cases .
In each test case:
The first line contains two integers NN, QQ. (1 \le N,Q \le 100000)(1≤N,Q≤100000) . NN is the length of the array AA .
Then one line contains NN integer indicating A[i]A[i] . (1 \le i \le N , 0 \le A[i] \le 1000000)(1≤i≤N,0≤A[i]≤1000000).
Then QQ lines follow . Each line two integer L,RL,R , means that there’s a query [L,R][L,R] . (1 \le L \le R \le N)(1≤L≤R≤N).
OutputFor each query, print the answer mod 10000000071000000007.
样例输入复制
1
3 1
1 2 3
1 3
样例输出复制
10
题目来源
SOLUTION:
FROM:https://www.cnblogs.com/RRRR-wys/p/9749591.html
首先,我们考虑拆位,分别计算每一位的贡献然后合并出答案,现在序列的元素只包含0或1。我们希望用线段树维护,异或为1的区间的个数,即包含奇数个1的区间的个数。那么,假设现在已知,[L,mid]有多少个区间包含奇数个1,[mid+1,R]有多少个区间包含奇数个1,那么合并后的区间的答案,就是左边的答案+右边的答案+横跨两个区间的答案。
横跨两个区间的答案 = (左边以mid为右端点包含奇数个1的区间的数目) * (右边以(mid+1)为左端点包含偶数个1的区间的数目) + (左边以mid为右端点包含偶数个1的区间的数目) * (右边以(mid+1)为左端点包含奇数个1的区间的数目)
那么现在就需要我们维护上边这4个东西,显然如果知道奇数的贡献,就很容易可以计算出偶数贡献。所以实际只用维护2个东西。这两个东西也可以用类似的思想维护出来,所以我们不用维护其他的东西了。引用大佬的话:“这类题目就是需要什么维护什么,直到数据结构自洽”当然,如果发现需要维护的东西过多,就要考虑换个思路了。
CODE:
#include <bits/stdc++.h>
#define pb push_back
typedef long long ll;
const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f3f;
const int mod = 1e9 + 7;
using namespace std;
int T, n, q, a[N];
struct node{
ll ans[20], lx[20], rx[20];
int num[20], len;
} tree[N<<2];
node mer(node &a,node &b) {
node res;
for(int i = 0; i < 20; ++i) {
res.ans[i] = a.ans[i] + b.ans[i];
res.ans[i] += a.lx[i]*(b.len - b.rx[i]);
res.ans[i] += (a.len - a.lx[i])*b.rx[i];
if(b.num[i] & 1) res.lx[i] = b.lx[i] + (a.len - a.lx[i]);
else res.lx[i] = b.lx[i] + a.lx[i];
if(a.num[i] & 1) res.rx[i] = a.rx[i] + (b.len - b.rx[i]);
else res.rx[i] = a.rx[i] + b.rx[i];
res.num[i] = a.num[i] + b.num[i];
}
res.len = a.len + b.len;
return res;
}
void build(int p, int l, int r) {
if(l == r) {
tree[p].len = 1;
for(int i = 0; i < 20; ++i)
if( a[l] & (1<<i) ) tree[p].ans[i] = tree[p].lx[i] = tree[p].rx[i] = tree[p].num[i] = 1;
else tree[p].ans[i] = tree[p].lx[i] = tree[p].rx[i] = tree[p].num[i] = 0;
return;
}
int mid = (l + r) >> 1;
build(p<<1, l, mid); build(p<<1|1, mid+1, r);
tree[p] = mer(tree[p<<1],tree[p<<1|1]);
}
node ask(int p,int l,int r,int L,int R) {
if(l == L && R == r) {
return tree[p];
}
int mid = (l + r) >> 1;
if(R <= mid) return ask(p<<1,l,mid,L,R);
else if(L > mid) return ask(p<<1|1,mid+1,r,L,R);
else {
node tmp1 = ask(p<<1,l,mid,L,mid);
node tmp2 = ask(p<<1|1,mid+1,r,mid+1,R);
return mer(tmp1,tmp2);
}
}
int main() {
scanf("%d", &T);
while( T-- ) {
scanf("%d%d",&n,&q);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
build(1,1,n);
while(q--) { int l, r;
scanf("%d %d",&l,&r);
node tmp = ask(1,1,n,l,r);
ll ans = 0;
for(int i = 19; i >= 0; --i)
ans = ((ans<<1LL)%mod + tmp.ans[i])%mod;
printf("%lld\n",ans);
}
}
return 0;
}