CodeForces - 617E - XOR and Favorite Number(前缀和+莫队)
题目链接:https://vjudge.net/problem/CodeForces-617E
题目大意:问题就是给你一个序列,问你询问的区间之内异或和为k的连续区间的数量
如果给的n不大的话,我们可以先考虑前缀和,设a[ ]为区间异或和,如果a[l, r]的异或和等于k,那么a[r]^a[l-1]^k = a[l-1],如果[1, 1]的异或和为k,那么a[1]^k就等于0,如果[1, 2]的异或和为k,那么a[2]^k等于0, 如果[1, 3]的异或和为k, 那么a[3]^k等于0, 如果[2, 3]的异或和等于0呢?那它的异或和就等于a[1], 因为a[3]是[1, 3]的异或和, 如果[2, 3]异或k等于0, 那结果就[1, 1],也就是a[1]但是光用前缀和肯定是不够的,这样的话复杂度会打到O(nm)所以说这时候就要套一个莫队算法了,另外有一个坑点是因为题目是异或所以int可能越界,注意开long long
#include<set> #include<map> #include<list> #include<stack> #include<queue> #include<cmath> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<climits> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define endl '\n' #define rtl rt<<1 #define rtr rt<<1|1 #define lson rt<<1, l, mid #define rson rt<<1|1, mid+1, r #define maxx(a, b) (a > b ? a : b) #define minn(a, b) (a < b ? a : b) #define zero(a) memset(a, 0, sizeof(a)) #define INF(a) memset(a, 0x3f, sizeof(a)) #define IOS ios::sync_with_stdio(false) #define _test printf("==============================================\n") using namespace std; typedef long long ll; typedef pair<int, int> P; typedef pair<ll, ll> P2; const double pi = acos(-1.0); const double eps = 1e-7; const ll MOD = 1000000007LL; const int INF = 0x3f3f3f3f; const int _NAN = -0x3f3f3f3f; const double EULC = 0.5772156649015328; const int NIL = -1; template<typename T> void read(T &x){ x = 0;char ch = getchar();ll f = 1; while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();} while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f; } const int maxn = 1e5+10; ll cnt[maxn*100], ans[maxn], sz; ll arr[maxn], res, k; struct Q { int l, r, k; friend bool operator < (Q x, Q y) { int a = x.l/sz, b = y.l/sz; return a == b ? x.r < y.r : a < b; } } q[maxn]; inline void add(int p) { res += cnt[arr[p]^k]; ++cnt[arr[p]]; } inline void sub(int p) { --cnt[arr[p]]; res -= cnt[arr[p]^k]; } int main(void) { int n, m; scanf("%d%d%lld", &n, &m, &k); for (int i = 1; i<=n; ++i) { scanf("%lld", &arr[i]); arr[i] ^= arr[i-1]; } for (int i = 0; i<m; ++i) { scanf("%d%d", &q[i].l, &q[i].r); q[i].k = i; } sz = sqrt(n)+eps; sort(q, q+m); cnt[0] = 1; int l = 1, r = 0; for (int i = 0; i<m; ++i) { while(q[i].l < l) add(--l-1); while(q[i].r > r) add(++r); while(q[i].l > l) sub(l++-1); while(q[i].r < r) sub(r--); ans[q[i].k] = res; } for (int i = 0; i<m; ++i) printf("%lld\n", ans[i]); return 0; }