qzqzgfy's blog

By qzqzgfy, history, 10 years ago, In English
E. XOR and Favorite Number
                                       617E
                            time limit per test4 seconds
                        memory limit per test256 megabytes
                                inputstandard input
                                outputstandard 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 n, m and k (1 ≤ n, m ≤ 100 000, 0 ≤ 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.

Sample test(s) 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

。。好题,我一开始觉得一定是按分块分的可持久化字典树,具体做法呢就是先利用莫队算法,然后将区间内的所有a[i]都加入字典树,然后对于每个节点我们都有对应能异或得k的所有对应节点,然后我们边修改l和r边修改ans。 然后因为位数在20左右,所以非常完美,不会爆炸。

以上都是yy,其实这题只要用一个sum【i】数组存一个前缀异或和,sum[r]^sum[l-1]就是a[l]到a[r]的异或和了,这样我们每加入一个sum[i]都有对应的op[sum[i]],这样我们再记录一个cnt[i]代表目前a[j]值为i的j的个数 这样ans就能+=cnt[i]*cnt[op[i]],此外,如果k=0,那么便有l=r的情况出现,然而k=0我们只需要特殊处理即可,此题还需要注意longlong,反正我把全部int改成long long了。 代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#define ll long long
struct wow{
	ll id,ans,l,r;
}ans[1000005];
ll l,r,mx,a[1000005],block,n,m,k,now,cnt[2000005],sum[1000005],op[2000005],pos[1000005];
bool cmp1(wow q,wow w){
	if (pos[q.l]==pos[w.l]) return q.r<w.r;
	return pos[q.l]<pos[w.l];
}
bool cmp2(wow q,wow w){
	return q.id<w.id;
}
void updata(ll x,ll v){
	if (k!=0)
	now-=cnt[sum[x]]*cnt[op[sum[x]]];
	else
	now-=((cnt[sum[x]]-1)*(cnt[sum[x]]))/2;
	cnt[sum[x]]+=v;
	if (k!=0)
	now+=cnt[sum[x]]*cnt[op[sum[x]]];
	else
	now+=((cnt[sum[x]]-1)*(cnt[sum[x]]))/2;
}
int main(){
	//freopen("tx.in","r",stdin);
	scanf("%I64d%I64d%I64d",&n,&m,&k);
	block=sqrt(n);
	for (int i=1;i<=n;i++)
	 pos[i]=i/block;
	for (int i=1;i<=n;i++)
	 scanf("%I64d",&a[i]);
	for (int i=1;i<=n;i++) 
	 sum[i]=sum[i-1]^a[i],mx=std::max(mx,sum[i]);
	for (int i=0;i<=mx;i++)
	 op[i]=i^k;
	for (int i=1;i<=m;i++){
		scanf("%I64d%I64d",&ans[i].l,&ans[i].r);
		ans[i].l--;
		ans[i].id=i;
		ans[i].ans=0;
	}  
	std::sort(ans+1,ans+1+m,cmp1);
    l=ans[1].l;r=ans[1].l;cnt[sum[l]]++;now=0;
    for (int i=1;i<=m;i++){
    	if (l<ans[i].l){
    		for (int j=l;j<ans[i].l;j++)
    		 updata(j,-1);
    	}
    	else
    	if (l>ans[i].l){
    		for (int j=l-1;j>=ans[i].l;j--)
    		 updata(j,1);
    	}
    	l=ans[i].l;
    	if (r<ans[i].r){
    		for (int j=r+1;j<=ans[i].r;j++)
    		 updata(j,1);
    	}
    	else
    	if (r>ans[i].r){
    		for (int j=r;j>ans[i].r;j--)
    		 updata(j,-1);
    	}
    	r=ans[i].r;
		ans[i].ans=now;    
    }
    std::sort(ans+1,ans+1+m,cmp2);
    for (int i=1;i<=m;i++)
     printf("%I64d\n",ans[i].ans);
} 
  • Vote: I like it
  • -26
  • Vote: I do not like it

»
10 years ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by qzqzgfy (previous revision, new revision, compare).

»
10 years ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by qzqzgfy (previous revision, new revision, compare).

»
10 years ago, hide # |
Rev. 2  
Vote: I like it 0 Vote: I do not like it

Too TM water le:)