codeforces #340 div 2 E XOR and Favorite Number

http://codeforces.com/contest/617/problem/E

题意:给出n个数,m个查询,每个查询给定l,r,问在区间【l,r】内,有多少对i,j,满足i^(i+1)^(i+2)^...^j的值为给定的常数k.

思路:学了莫队算法以后。。。这题果然是莫队的一眼题。

入手点是,知道异或也像加一样有前缀和性质。如果我们处理一个按照异或规则的前缀和数组sum[i]=sum[i-1]^a[i],那么i到j的异或和就是sum[i-1]^sum[j]  (x^x==0,因此a[1]到a[i-1]的异或和被去掉了)

因此我们要找的就是区间内有多对i,j满足sum[i-1]^sum[j]==k,也就是sum[i-1]==k^sum[j]这和hdu 5213 a=k-b有如此类似的形式,做法也是类似的。

由于对于每个j,找的是i-1,在处理的时候记得将区间左端点-1,

最重要的一点是,莫队的添加和删除操作最好分开写,至少根据d的正负写个if else,因为顺序不一定相同。

最后一个注意的是,可能会爆int ,所以要用long long

/* ***********************************************
Author :111qqz
Created Time :2016年02月13日 星期六 21时47分47秒
File Name :code/cf/#340/E.cpp
************************************************ */
 1#include <cstdio>
 2#include <cstring>
 3#include <iostream>
 4#include <algorithm>
 5#include <vector>
 6#include <queue>
 7#include <set>
 8#include <map>
 9#include <string>
10#include <cmath>
11#include <cstdlib>
12#include <ctime>
13#define fst first
14#define sec second
15#define lson l,m,rt<<1
16#define rson m+1,r,rt<<1|1
17#define ms(a,x) memset(a,x,sizeof(a))
18typedef long long LL;
19#define pi pair < int ,int >
20#define MP make_pair
 1using namespace std;
 2const double eps = 1E-8;
 3const int dx4[4]={1,0,0,-1};
 4const int dy4[4]={0,-1,1,0};
 5const int inf = 0x3f3f3f3f;
 6const int N=3E6+7;
 7int n,m,k;
 8int siz;
 9LL a[N];
10LL sum[N];
11int pos[N];
12LL cur;
13LL cnt[N];
14LL ans[N];
1struct node
2{
3    int l,r;
4    int id;
1    bool operator <(node b)const
2    {
3	if (pos[l]==pos[b.l])
4	    return r<b.r;
5	return pos[l]<pos[b.l];
6    }
7}q[N];
void update ( int x,int d)
{
 1  /* cnt[sum[x]]+=d;
 2   // if (sum[x]^k>3E7) return;
 3   // cout<<"pp:"<<pp<<endl;
 4    cur = cur + d*(cnt[sum[x]^k]);  */
 5    if (d>0)
 6    {
 7//	cnt[sum[x]]++;
 8	cur +=cnt[sum[x]^k];
 9	cnt[sum[x]]++;   //两种更新的顺序不一定一样,所以最好还是分开写....//why?
10    }
11    else
12    {
13	cnt[sum[x]]--;
14	cur -=cnt[sum[x]^k];
15    }
16}
17int main()
18{
19	#ifndef  ONLINE_JUDGE 
20	freopen("code/in.txt","r",stdin);
21  #endif
22	cin>>n>>m>>k;
23	ms(cnt,0);
24	int siz = 340;
1	ms(sum,0);
2	ms(pos,-1);
3	for ( int i = 1 ; i <= n ; i++)
4	{
5	    scanf("%I64d",&a[i]);
6	    sum[i] = sum[i-1] ^ a[i];
7        pos[i] = (i-1)/siz;
8	}
	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);

//	for ( int i = 1;i  <= m ; i++) cout<<"l r id "<<q[i].l<<" "<<q[i].r<<" "<<q[i].id<<endl;
1	cur = 0LL ; 
2	int pl = 1 ;
3	int pr = 0;
4	for ( int i = 1 ; i <= m ; i++)
5	{
6	    int id = q[i].id;
7	    int l = q[i].l-1; //此处需要注意,因为是i到j的异或和是sum[i-1]^sum[j]
8	    int r = q[i].r;
1	    if (r<pr)
2	    {
3		for ( int j = r +1 ; j <= pr ; j ++) update(j,-1);
4	    }
5	    else
6	    {
7		for ( int j = pr +1 ; j <= r ; j ++) update(j,1);
8	    }
	    pr = r;
1	    if (l<pl)
2	    {
3		for ( int j = l ; j <= pl-1 ; j++) update(j,1);
4	    }
5	    else
6	    {
7		for ( int j = pl ;  j <= l-1 ; j++) update(j,-1);
8	    }
	    pl = l;
	    ans[id] = cur;
1	}
2	for ( int i = 1 ;i <= m ; i++) printf("%I64d\n",ans[i]);
3  #ifndef ONLINE_JUDGE  
4  fclose(stdin);
5  #endif
6    return 0;
7}