CF 617E【莫队求区间异或和】
题目大意:
给定长度为n的序列,m个询问和常数K
多个询问L,R,求有多少对(i,j)满足L<=i<=j<=R且i到j异或和为K
分析:
这题妙啊
总结经验
1.看到多个询问L,R的要考虑到莫队
2.看到区间异或和的要想到转化成前缀和,变成Si^Sj==K的简化问题
3.看到异或的时候要考虑到,经过异或权值范围会比数据中给得大(异或一下权值就不是原范围了)
3.看到权值不是很大的情况下,考虑能不能用桶
4.看到求多少对的问题要注意开long long
5.区间异或和转换成前缀和后,实际取值中i为L-1<=i<R,要特判加上L-1的贡献(就类似于树上莫队特判lca)
转载自acha
2017-04-06
Select Code
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=4e5+5;
typedef long long ll;
struct block{int l,r,id;}Q[N];
int n,m,K,bsize,a[N];
ll nowans,ans[N],cnt[N*10];
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
bool operator <(const block &a,const block &b){
return a.l/bsize!=b.l/bsize?a.l/bsize<b.l/bsize:a.r<b.r;
}
inline void ins(int x){
nowans+=cnt[K^x];
cnt[x]++;
}
inline void del(int x){
cnt[x]--;
nowans-=cnt[K^x];
}
int main(){
n=read();m=read();K=read();bsize=sqrt(n+0.5);
for(int i=1;i<=n;i++) a[i]=read(),a[i]^=a[i-1];
for(int i=1;i<=m;i++) Q[i].l=read(),Q[i].r=read(),Q[i].id=i;
sort(Q+1,Q+m+1);
int l=1,r=0;
for(int i=1;i<=m;i++){
while(l>Q[i].l) ins(a[--l]);
while(l<Q[i].l) del(a[l++]);
while(r<Q[i].r) ins(a[++r]);
while(r>Q[i].r) del(a[r--]);
ans[Q[i].id]=nowans+cnt[K^a[l-1]];
}
for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
return 0;
}
#include<cstdio> #include<cmath> #include<algorithm> #define EF if(ch==EOF) return EOF; #define EX if(ch==EOF) return x*f; using namespace std; const int N=4e5+5; struct node{int l,r,id;}q[N]; int n,m,k,bsize,a[N]; long long nowans,ans[N],cnt[N*10]; inline int read(){ int x=0,f=1;char ch=getchar();EF while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();EF} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();EX} return x*f; } inline bool cmp(const node &a,const node &b){ return a.l/bsize!=b.l/bsize?a.l/bsize<b.l/bsize:a.r<b.r; } inline void ins(int x){ nowans+=cnt[k^x]; cnt[x]++; } inline void del(int x){ cnt[x]--; nowans-=cnt[k^x]; } int main(){ n=read();m=read();k=read(); for(int i=1;i<=n;i++) a[i]=read(),a[i]^=a[i-1]; for(int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i; bsize=sqrt(n); sort(q+1,q+m+1,cmp); int l=q[1].l,r=q[1].r; for(int i=l;i<=r;i++) ins(a[i]); ans[q[1].id]=nowans+cnt[k^a[l-1]]; for(int i=2;i<=m;i++){ while(q[i].l<l) ins(a[--l]); while(q[i].r>r) ins(a[++r]); while(q[i].l>l) del(a[l++]); while(q[i].r<r) del(a[r--]); ans[q[i].id]=nowans+cnt[k^a[l-1]]; } for(int i=1;i<=m;i++) printf("%I64d\n",ans[i]); return 0; }
referance:
http://codeforces.com/blog/entry/22971(官方解题报告)
http://blog.csdn.net/qq978874169/article/details/51241737(莫队算法入门)