• CodeForces


    题意:

      n个数m次查询,每次查询给出l,r求子区间异或和为k的个数。

    题解:

      预处理前缀异或和,因为是区间相减求满足的所以左区间要减1。要注意数组要开2e6因为两个1e6的数异或可能会更大,答案也要开long long。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+10;
    const int maxm = 2e6+10;
    typedef long long ll;
    int n, m, k;
    int blk;
    int l, r;
    ll now;
    ll ans[maxn];
    int sum[maxm], cnt[maxm];
    struct ask {
        int x, y, qx, id;
        friend bool operator < (ask a, ask b) {
            return a.qx==b.qx?a.y<b.y:a.x<b.x;
        }
    }q[maxn];
    void update(int x, int t) {
        if(t > 0) {
            now += cnt[sum[x]^k];
            cnt[sum[x]]++;
        }
        else {
            cnt[sum[x]]--;
            now -= cnt[sum[x]^k];
        }
    }
    int main() {
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1; i <= n; i++) scanf("%d", &sum[i]), sum[i] ^= sum[i-1];
        blk = sqrt(n);
        for(int i = 1; i <= m; i++) {
            scanf("%d%d", &q[i].x, &q[i].y);
            q[i].qx = (q[i].x-1)/blk+1;
            q[i].id = i;
        }
        sort(q+1, q+m+1);
        l = 1; r = 0;
        for(int i = 1; i <= m; i++) {
            while(l < q[i].x-1) update(l++, -1);
            while(l > q[i].x-1) update(--l, 1);
            while(r < q[i].y) update(++r, 1);
            while(r > q[i].y) update(r--, -1);
            ans[q[i].id] = now;
        }
        for(int i = 1; i <= m; i++) printf("%lld
    ", ans[i]);
        return 0;
    } 
    View Code
  • 相关阅读:
    1295: [SCOI2009]最长距离
    [vijos p1028] 魔族密码
    HJ浇花
    1060: [ZJOI2007]时态同步
    1816: [Cqoi2010]扑克牌
    1800: [Ahoi2009]fly 飞行棋
    4300: 绝世好题
    1237: [SCOI2008]配对
    1801: [Ahoi2009]chess 中国象棋
    1189: [HNOI2007]紧急疏散evacuate
  • 原文地址:https://www.cnblogs.com/Pneuis/p/8604468.html
Copyright © 2020-2023  润新知