6759: 异或序列

6759: 异或序列

时间限制: 1 Sec  内存限制: 128 MB

题目描述

已知一个长度为n的整数数列a1,a2,…,an,给定查询参数l、r,问在al,al+1,…,ar区间内,有多少子序列满足异或和等于k。也就是说,对于所有的x,y(l≤x≤y≤r),满足ax⊕ax+1⊕⋯⊕ay=k的x,y有多少组。

输入

输入第一行为3个整数n,m,k。第二行为空格分开的n个整数,即a1,a2,…,an。接下来m行,每行两个整数lj,rj,代表一次查询。

输出

输出共m行,对应每个查询的计算结果。

样例输入

4 5 1
1 2 3 1
1 4
1 3
2 3
2 4
4 4

样例输出

4
2
1
2
1

提示

对于30%的数据,1≤n,m≤1000。
对于100%的数据,1≤n,m≤105,0≤k,ai≤105,1≤lj≤rj≤n。

来源/分类

重庆OI2018 

看到多次区间查询,就想到了莫队算法,但是莫队中对于区间状态转移的处理却是需要斟酌。

题目已经很明显的提示了,异或异或,也许我们应该使用异或前缀和,(orz)

对于异或前缀和 我们知道 i and j 之间的异或和 == sum[j]^sum[i-1] 

那么对于l 如果小于 Q.l-1,那么我们就先清除这位置的影响,然后下标++

如果大于Q.l-1,那就下标--,再加上这位置影响

我们要让求异或为k的组合数

sum[j] ^ sum[i] = k 即 sum[j] ^ k = sum[i]

用cnt 记录 区间内前缀和的数量变化

那么ans += val * (cnt[sum[j] ^ k])即这个点所造成的k组数影响

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<math.h>
 4 #include<algorithm>
 5 using namespace std;
 6  
 7 const int maxn = 1e5+5;
 8 int n,m,k;
 9 int block;
10 int sum[maxn];
11 int ans;
12 int tmp;
13 int cnt[maxn];
14  
15 struct node
16 {
17     int l,r,id,ans;
18     friend bool operator < (const node &a,const node&b)
19     {
20         if(a.l / block != b.l / block)return a.l < b.l;
21         return a.r < b.r;
22     }
23     node(){}
24     node(int l,int r,int id):l(l),r(r),id(id){}
25 }Q[maxn];
26  
27 bool cmp(node a,node b)
28 {
29     return a.id < b.id;
30 }
31  
32 void revise(int x,int val)
33 {
34     cnt[sum[x]]+=val;
35     ans += val*cnt[sum[x]^k];
36 }
37 int main()
38 {
39     scanf("%d%d%d",&n,&m,&k);
40     block = sqrt(n);
41     for(int i=1;i<=n;i++)
42     {
43         scanf("%d",&tmp);
44         sum[i] = tmp ^ sum[i-1];
45     }
46     for(int i=1;i<=m;i++)
47     {
48         scanf("%d%d",&Q[i].l,&Q[i].r);
49         Q[i].id = i;
50     }
51     sort(Q+1,Q+m+1);
52     int l = 1,r = 0;
53     ans = 0;
54     for(int i=1;i<=m;i++)
55     {
56         while(l < Q[i].l - 1)revise(l,-1),l++;
57         while(l > Q[i].l - 1) l--,revise(l,1);
58         while(r < Q[i].r)r++,revise(r,1);
59         while(r > Q[i].r)revise(r,-1),r--;
60         Q[i].ans = ans;
61     }
62     sort(Q+1,Q+m+1,cmp);
63     for(int i=1;i<=m;i++)printf("%d
",Q[i].ans);
64     return 0;
65 }
View Code
原文地址:https://www.cnblogs.com/iwannabe/p/9539460.html