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; }