【莫队算法】codeforces 617e

传送门:XOR and Favorite Number

题意:
给一个不可变序列,每次询问一个区间,问这个区间里有多少个不同的数异或后,可以使得 xor k == 0

思路:
不难可以想到用莫队,但是用莫队来维护什么东西呢
我们可以想到,如果一个区间的异或值是a,a ^ k = b,那么如果存在b的情况数,那么答案可以加上b的情况数。
而当b = 0的时候,一定有一种情况数。
我们可以先作一个前缀和把a的前缀异或求出来

这里要特别注意,维护莫队左右指针的时候。
当我们移动左指针的时候,由于异或的情况数是由b得到的,我们要去掉a的时候,应该要去掉a位置的前面一个,因为组合出来的a的靠a当前位置异或上前面的前缀和。
所以我们应该要去掉a前面一个位置的前缀和的计数器。

#include <bits/stdc++.h>

#define MAXN 2000005
#define ll long long

using namespace std;

struct Question {
    int l, r, idx;  
} qsn[MAXN];

ll ans, k;
int pos[MAXN];
int flag[MAXN];
int a[MAXN];
ll lans[MAXN];

int cmp(Question a, Question b) {
    if (pos[a.l] != pos[b.l]) {
        return pos[a.l] < pos[b.l];
    }
    return a.r < b.r;
}

void add(int x) {
    ans += flag[a[x] ^ k];
    flag[a[x]]++;
}

void del(int x) {
    flag[a[x]]--;
    ans -= flag[a[x] ^ k];  
}

int main() {
    int n, q;
    scanf("%d %d %lld", &n, &q, &k);
    int s = sqrt(n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        a[i] ^= a[i - 1];
        pos[i] = i / s;
    }
    for (int i = 1; i <= q; i++) {
        scanf("%d %d", &qsn[i].l, &qsn[i].r);
        qsn[i].idx = i;
    }
    sort(qsn + 1, qsn + q + 1, cmp);
    flag[0] = 1;
    ans = 0;
    int l = 1, r = 0;
    for (int i = 1; i <= q; i++) {
        while (qsn[i].l < l) {
            add(--l - 1);
        }
        while (qsn[i].l > l) {
            del(l++ - 1);
        }
        while (qsn[i].r < r) {
            del(r--);
        }
        while (qsn[i].r > r) {
            add(++r);
        }
        lans[qsn[i].idx] = ans;
    }
    for (int i = 1; i <= q; i++) {
        printf("%lld\n", lans[i]);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值