#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))
#define MAXN 100000 + 10
#define MAXK 10000000 + 10
/**
题目大意
给一个数列 和数字k 多次询问[l, r]范围内 有多少各连续子序列
异或值为k
思路
没有区间修改 用莫队需要用O(1)复杂度转移
预处理 pre[x] 表示 0 ~ x 的数的异或值
则 i ~ j 的异或值为 pre[i - 1] ^ pre[j]
当在右边增加时询问 区间内(包括开区间下届) pre[j] ^ k 的个数
当在左边增加时询问 区间内 pre[i - 1] ^ k 的个数
简单的用两个hash维护下届开区间和闭区间内的各pre个数
*/
using namespace std;
int sqn;
struct query
{
int l, r;
int id;
__int64 ans;
} q[MAXN];
__int64 a[MAXN], pre[MAXN], book[MAXK], book1[MAXK], ans, k;
bool cmp(query a, query b)
{
if (a.l / sqn == b.l / sqn)
return a.r < b.r;
return a.l < b.l;
}
bool CMP(query a, query b)
{
return a.id < b.id;
}
void add(int x, bool flag)
{
book[pre[x]]++;
if (x > 0)
book1[pre[x - 1]]++;
else
book1[0]++;
if (flag)
{
if (x > 0)
ans += book[pre[x - 1] ^ k];
else
ans += book[0 ^ k];
}
else
{
ans += book1[pre[x] ^ k];
}
}
void del(int x, bool flag)
{
if (flag)
{
if (x > 0)
ans -= book[pre[x - 1] ^ k];
else
ans -= book[0 ^ k];
}
else
ans -= book1[pre[x] ^ k];
book[pre[x]]--;
if (x > 0)
book1[pre[x - 1]]--;
else
book1[0]--;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
int n, m;
__int64 tmp;
mem(book, 0);
mem(book1, 0);
scanf("%d %d %d", &n, &m, &k);
//cout << n << " " << m <<endl;
sqn = sqrt(n);
for (int i = 0; i < n; i++)
{
scanf("%I64d", a + i);
if (i == 0)
{
pre[i] = a[i];
tmp = a[i];
}
else
{
pre[i] = tmp ^ a[i];
tmp = pre[i];
}
}
int l, r;
for (int i = 0; i < m; i++)
{
scanf("%d %d", &l, &r);
q[i].l = l - 1;
q[i].r = r;
q[i].id = i;
}
sort(q, q + m, cmp);
ans = 0;
l = r = 0;
for (int i = 0; i < m; i++)
{
while (r < q[i].r)
{
add(r, 0);
r++;
}
while (l > q[i].l)
{
l--;
add(l, 1);
}
while (r > q[i].r)
{
r--;
del(r, 0);
}
while (l < q[i].l)
{
del(l, 1);
l++;
}
q[i].ans = ans;
}
sort(q, q + m, CMP);
for (int i = 0; i < m; i++)
printf("%I64d\n", q[i].ans);
return 0;
}
CodeForces - 617E_XOR and Favorite Number(莫队)
猜你喜欢
转载自blog.csdn.net/Anna__1997/article/details/78573102
今日推荐
周排行