CODEFORCES 340 XOR and Favorite Number 莫队模板题

原来我直接学的是假的莫队

原题:

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.

1 ≤ n, m ≤ 100 000, 0 ≤ k ≤ 1 000 000, 0 ≤ ai ≤ 1 000 000

题意:

给定一个数列a[i],你可以通过异或前缀和求出s[i],每次求出[l-1,r]内s[i] xor s[j]=k的(i,j)的对数

 

模板题,先分块,左端点所在块为第一关键字,右端点为第二关键字排序

然后记录一个l和r,每次直接暴力让l和r走到查询的两端点即可

我之前一直以为块间跳转是当两端点中间有一个或多个块的时候加上中间的块的值

经过jjh和sqy大神的指点才知道原来分块就是指排序的时候分块,处理的时候暴力走就可以了

我学了假的分块

有一些细节需要注意,首先所有的操作都是建立在异或前缀和上的所以输入的时候要搞前缀和,而且算答案的时候l要-1

一般n<1e5求数对的个数一般会爆int,要注意longlong

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<vector>
 7 using namespace std;
 8 #define ll long long
 9 int rd(){int z=0,mk=1;  char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
11     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
12     return z*mk;
13 }
14 struct dcd{int x,y,id;}b[110000];
15 int n,m,k,a[110000];
16 int blck;
17 ll cnt[1100000],ans[110000];
18 ll bwl=0;
19 inline void ist(int x){  bwl+=cnt[a[x]^k],++cnt[a[x]];}
20 inline void dlt(int x){  --cnt[a[x]],bwl-=cnt[a[x]^k];}
21 bool cmp(dcd x,dcd y){  return(x.x/blck==y.x/blck)?(x.y<y.y):(x.x/blck<y.x/blck);}
22 int main(){//freopen("ddd.in","r",stdin);
23     cin>>n>>m>>k;  blck=(int)sqrt(n*1.0);
24     for(int i=1;i<=n;++i)  a[i]=rd(),a[i]^=a[i-1];
25     for(int i=1;i<=m;++i)  b[i].x=rd(),b[i].y=rd(),b[i].id=i;
26     sort(b+1,b+m+1,cmp);
27     int l=1,r=0;  cnt[0]=1;
28     for(int i=1;i<=m;++i){
29         while(l<b[i].x)  dlt(l-1),++l;
30         while(l>b[i].x)  l--,ist(l-1);
31         while(r<b[i].y)  ist(++r);
32         while(r>b[i].y)  dlt(r--);
33         ans[b[i].id]=bwl;
34     }
35     for(int i=1;i<=m;++i)  printf("%I64d\n",ans[i]);
36     return 0;
37 }
View Code

 

转载于:https://www.cnblogs.com/JSL2018/p/6426395.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值