莫队算法只能离线的进行查询,不能在线的进行修改。通过改变查询的顺序,从而降低算法的时间复杂度。
题目
XOR and Favorite Number
题意
- 给定n个数,然后给出m个询问,每一个询问为[L, R]区间内的询问。问区间内有多少对数,使得它们连续的亦或为k.
题解
- 我们可以预处理亦或的前缀和pre[],那么当求[l, r]区间内的亦或和时,直接用pre[l-1]^pre[r]来求一个区间的亦或和。
- 用莫队的思想,对查询进行排序,从而降低算法的时间复杂度。\(O(n\sqrt{n})\)
代码
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
 | #include <bits/stdc++.h> using namespace std; const int maxn = 2e6+10; typedef long long LL; LL a[maxn]; struct Node{     int l ,r, id; }Q[maxn]; int pos[maxn]; LL ans[maxn]; LL flag[maxn]; bool cmp(Node a, Node b){     if(pos[a.l] == pos[b.l]){         return a.r<b.r;     }     return pos[a.l] < pos[b.l]; } int n, m, k; int L = 1, R = 0; LL Ans = 0; void del(int index){     flag[a[index]]--;     Ans -= flag[a[index]^k]; } void add(int index){     Ans += flag[a[index]^k];     flag[a[index]]++; } int main() {     while(~scanf("%d%d%d", &n, &m, &k)){         L = 1, R = 0, Ans = 0;         memset(flag, 0, sizeof(flag));         a[0] = 0;         int sz = sqrt(n);         for(int i=1; i<=n; i++){             scanf("%d", &a[i]);             a[i] ^= a[i-1];             pos[i] = i/sz;         }         for(int i=1; i<=m; i++){             scanf("%d%d", &Q[i].l, &Q[i].r);             Q[i].id = i;         }         sort(Q+1, Q+m+1, cmp);         flag[0] = 1;         for(int i=1; i<=m; i++){             while(Q[i].l>L){                 del(L-1);                 L++;             }             while(Q[i].l<L){                 L--;                 add(L-1);             }             while(Q[i].r>R){                 R++;                 add(R);             }             while(Q[i].r<R){                 del(R);                 R--;             }             ans[Q[i].id] = Ans;         }         for(int i=1; i<=m; i++){             printf("%I64d\n", ans[i]);         }     }     return 0; }
 | 
未解决的问题