Codeforces 617E XOR and Favorite Number莫队
http://codeforces.com/contest/617/problem/E
题意:给出q个查询,每次询问区间内连续异或值为k的有几种情况。
思路:没有区间修改,而且扩展端点,减小端点在前缀和的处理下都是O(n)的,使用莫队算法,每次移动区间时,注意计数是否先减.
/** @Date : 2016-12-09-19.31
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version :
*/
#include<bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;
struct sion
{
int l, r;
int id;
}s[N];
LL a[N];
LL cnt[N*100];
int blc[N];
LL res[N];
int cmp(sion a, sion b)
{
if(blc[a.l] == blc[b.l])
return a.r < b.r;
return a.l < b.l;
}
int main()
{
int n, q, k;
cin >> n >> q >> k;
a[0] = 0;
for(int i = 1; i <= n; i++)
{
scanf("%lld", a + i);
a[i] = a[i] ^ a[i-1];
}
int dlt = sqrt(n);
for(int i = 1; i <= n; i++)
{
blc[i] = (i - 1)/dlt + 1;
}
for(int i = 1; i <= q; i++)
{
scanf("%d%d", &s[i].l, &s[i].r);
s[i].id = i;
}
sort(s + 1, s + 1 + q, cmp);
MMF(cnt);
cnt[0] = 1;
LL ans = 0;
int l = 0, r = 0;//前缀和的关系l初始为0
for(int i = 1; i <= q; i++)
{
while(l > s[i].l - 1)//一定要注意边界问题
l--, ans += cnt[k ^ a[l]], cnt[a[l]]++;//扩增区间先增加下标
while(r < s[i].r)
r++, ans += cnt[k ^ a[r]], cnt[a[r]]++;
while(l < s[i].l - 1)
cnt[a[l]]--,ans -= cnt[k ^ a[l]], l++;//缩小区间,由于前缀和的关系,先计数减1
while(r > s[i].r)
cnt[a[r]]--,ans -= cnt[k ^ a[r]] , r--;
res[s[i].id] = ans;
}
for(int i = 1; i <= q; i++)
printf("%lld\n", res[i]);
return 0;
}

浙公网安备 33010602011771号