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

posted @ 2016-12-09 22:19  Lweleth  阅读(171)  评论(0编辑  收藏  举报