题意:
给定一个长度为 n 的数组 a 和一个数字 k,有 m 次询问,每次询问区间 [ l, r ] 中满足有多少个二元组 ( i, j ) 满足 l <= i <= j <= r 且 。(n, m <= 1e5, k, ai <= 1e6)
链接:
https://vjudge.net/problem/CodeForces-617E
解题思路:
对于区间连续异或和,令 , , 则条件转化为求有多少个二元组( i, j ) 满足 l - 1 <= i < j <= r 且 a[ i ] ^ a[ j ] = k,注意 i ≠ j,即元素不为空,然后用莫队转移答案即可。
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define sz(a) ((int)a.size())
#define mem(a, b) memset(a, b, sizeof a)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e5 + 5;
const int maxm = 5e2 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int id[maxn];
struct Qr{
int l, r, p;
bool operator < (const Qr &o) const{
return id[l] == id[o.l] ? (id[l] & 1 ? r > o.r : r < o.r) : id[l] < id[o.l];
}
} qr[maxn];
int a[maxn], sum[1 << 21];
ll ans[maxn], ret;
int n, m, k;
void add(int x){
ret += sum[x ^ k];
++sum[x];
}
void del(int x){
--sum[x];
ret -= sum[x ^ k];
}
int main(){
// ios::sync_with_stdio(0); cin.tie(0);
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for(int i = 1; i <= n; ++i) a[i] ^= a[i - 1];
for(int i = 1; i <= m; ++i){
int l, r; scanf("%d%d", &l, &r);
qr[i] = { l, r, i };
}
int len = sqrt(n);
for(int i = 1; i <= n; ++i) id[i] = (i - 1) / len + 1;
int l = 1, r = 0;
sort(qr + 1, qr + 1 + m);
for(int i = 1; i <= m; ++i){
--qr[i].l;
while(l > qr[i].l) --l, add(a[l]);
while(r < qr[i].r) ++r, add(a[r]);
while(l < qr[i].l) del(a[l]), ++l;
while(r > qr[i].r) del(a[r]), --r;
ans[qr[i].p] = ret;
}
for(int i = 1; i <= m; ++i) printf("%lld\n", ans[i]);
return 0;
}