Codeforeces 617E XOR and Favorite Number(莫队+小技巧)

E. XOR and Favorite Number
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Bob has a favorite number k and ai of length n. Now he asks you to answer m queries. Each query is given by a pair li and ri and asks you to count the number of pairs of integers i and j, such that l ≤ i ≤ j ≤ r and the xor of the numbers ai, ai + 1, ..., aj is equal to k.

Input

The first line of the input contains integers nm and k (1 ≤ n, m ≤ 100 0000 ≤ k ≤ 1 000 000) — the length of the array, the number of queries and Bob's favorite number respectively.

The second line contains n integers ai (0 ≤ ai ≤ 1 000 000) — Bob's array.

Then m lines follow. The i-th line contains integers li and ri (1 ≤ li ≤ ri ≤ n) — the parameters of the i-th query.

Output

Print m lines, answer the queries in the order they appear in the input.

Examples
input
6 2 3
1 2 1 1 0 3
1 6
3 5
output
7
0
input
5 3 1
1 1 1 1 1
1 5
2 4
1 3
output
9
4
4
Note

In the first sample the suitable pairs of i and j for the first query are: (12), (14), (15), (23), (36), (56), (66). Not a single of these pairs is suitable for the second query.

In the second sample xor equals 1 for all subarrays of an odd length.

 

 

题目链接:CF 617E

这题感觉比一般的莫队要难很多,主要问题就出在转化上,一开始看感觉没办法O(1)进行拓展,后来看了大牛的思路原来是用了一个前缀异或和的数组pre[ ]和一个维护当前区间内异或和个数的数组cnt[ ],用pre[i-1]^pre[j]来表示ai^……aj的异或和,这样才能写出add和del函数。

假设当前已知【L,R】,如果区间增加,假设增加的那个位置的值为pre[x],那么显然pre[x]可以和区间内所有值为 k^pre[x]的数进行两两组合,即会多出cnt[ k^pre[x] ]个组合,此时cnt就可以用到,直接加上cnt[k^pre[x]]即可,然后再更新pre[x](顺序不能反,万一pre[x]^k和pre[x]是相同的,更新前是4,更新后是5,但是只能多出4个组合而不是5个组合);如果区间减小,由于被减掉的那个pre[x]本来可以组合cnt[k^pre[x]]个,因此要减掉这么多个数,但是假如pre[x]=pre[x]^k的话,比如5个0去了一个0变成了4个0,组合数减少了4,因此要先自减1再更新此时的答案

代码:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<bitset>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=1<<20;

struct info
{
    int l,r;
    int b,idd;
    bool operator<(const info &t)const
    {
        if(b==t.b)
            return r<t.r;
        return b<t.b;
    }
};

info query[N];
int pre[N];
LL cnt[N];
LL ans[N];
void init()
{
    CLR(pre,0);
    CLR(cnt,0);
    CLR(ans,0);
}
inline void add(const int &val,LL &temp,const int &k)
{
    temp+=cnt[val^k];
    ++cnt[val];
}
inline void del(const int &val,LL &temp,const int &k)
{
    --cnt[val];
    temp-=cnt[val^k];;
}
int main(void)
{
    int n,m,k,i,j,val;
    while (~scanf("%d%d%d",&n,&m,&k))
    {
        init();
        for (i=1; i<=n; ++i)
        {
            scanf("%d",&val);
            pre[i]=pre[i-1]^val;
        }
        int unit=sqrt(n);
        for (i=0; i<m; ++i)
        {
            scanf("%d%d",&query[i].l,&query[i].r);
            query[i].b=query[i].l/unit;
            query[i].idd=i;
        }
        sort(query,query+m);
        int L=1,R=0;
        LL temp=0;
        cnt[0]=1;
        for (i=0; i<m; ++i)
        {
            while (L>query[i].l)
            {
                --L;
                add(pre[L-1],temp,k);
            }
            while (L<query[i].l)
            {
                del(pre[L-1],temp,k);
                ++L;
            }
            while (R>query[i].r)
            {
                del(pre[R],temp,k);
                --R;
            }
            while (R<query[i].r)
            {
                ++R;
                add(pre[R],temp,k);
            }
            ans[query[i].idd]=temp;
        }
        for (i=0; i<m; ++i)
            printf("%I64d\n",ans[i]);
    }
    return 0;
}
posted @ 2016-09-04 18:06  Blackops  阅读(247)  评论(0编辑  收藏  举报