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.node
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.ios
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.數組
Print m lines, answer the queries in the order they appear in the input.markdown
6 2 3
1 2 1 1 0 3
1 6
3 5app
7
0ui
5 3 1
1 1 1 1 1
1 5
2 4
1 3spa
9
4
4code
In the first sample the suitable pairs of i and j for the first query are: (1, 2), (1, 4), (1, 5), (2, 3), (3, 6), (5, 6), (6, 6). 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.
題意:有n個數和m次詢問,每一詢問會有一個L和R,表示所詢問的區間,問在這個區間中有多少個連續的子區間的亦或和爲k
思路:本題只有詢問沒有修改,因此比較適合離線處理,而莫隊算法是離線處理一類區間不修改查詢類問題的算法。就是若是你知道了[L,R]的答案。你能夠在O(1)的時間下獲得[L,R-1]和[L,R+1]和[L-1,R]和[L+1,R]的答案的話。就可使用莫隊算法。,第一次接觸莫隊算法感受是一種很優雅的暴力,莫隊算法是莫濤發明的。先對序列分塊。而後對於全部詢問按照L所在塊的大小排序。若是同樣再按照R排序。而後按照排序後的順序計算。爲何這樣計算就能夠下降複雜度呢。
1、i與i+1在同一塊內,r單調遞增,因此r是O(n)的。因爲有n^0.5塊,因此這一部分時間複雜度是n^1.5。
2、i與i+1跨越一塊,r最多變化n,因爲有n^0.5塊,因此這一部分時間複雜度是n^1.5
3、i與i+1在同一塊內時變化不超過n^0.5,跨越一塊也不會超過2*n^0.5,不妨看做是n^0.5。因爲有n個數,因此時間複雜度是n^1.5因而就變成了O(n^1.5)了。
對於這道題,假設咱們如今有一個前綴異或和數組sum[],如今咱們要求區間[L,R]的異或的值,用sum數組表示就是sum[L-1]^sum[R]==K,或者說是K^sum[R]==sum[L-1]
詳細見代碼
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const int Max = 1100000;
const int MAXM = 1<<22;
typedef struct node
{
int L ,R;
int Id;
}Point ;
Point a[Max];
LL sum[Max];
LL ans[Max];
int n,m;
LL k;
int L,R;
LL cnt[MAXM],ant;
bool cmp(Point b,Point c)//將區間分塊排序
{
if(b.L/400==c.L/400)
{
return b.R<c.R;
}
else
{
return b.L<c.L;
}
}
void Dec(LL s) //將多算的數目去除
{
--cnt[s];
ant-=cnt[s^k];
}
void Inc(LL s)//將沒有遍歷的點對應的數目加上
{
ant += cnt[s^k];
cnt[s]++;
}
int main()
{
scanf("%d %d %lld",&n,&m,&k);
LL data;
for(int i=1;i<=n;i++) //
{
scanf("%lld",&sum[i]);
sum[i]^=sum[i-1];
}
for(int i=1;i<=m;i++)
{
scanf("%d %d",&a[i].L,&a[i].R);
a[i].Id = i;
a[i].L--;// 在這裏提早處理
}
sort(a+1,a+m+1,cmp);
L=0,R=0,cnt[0]=1,ant=0;
for(int i=1;i<=m;i++)
{
while(R<a[i].R)
{
Inc(sum[++R]);
}
while(R>a[i].R)
{
Dec(sum[R--]);
}
while(L<a[i].L)
{
Dec(sum[L++]);
}
while(L>a[i].L)
{
Inc(sum[--L]);
}
ans[a[i].Id]=ant;
}
for(int i=1;i<=m;i++)
{
printf("%lld\n",ans[i]);
}
return 0;
}