[CQOI2018]异或序列 题解

转化题意

给n个整数,给一个值k,m个询问,每个询问给出一个区间,求区间里有多少对数异或为k

 


注意到n个整数的值比较小,可以用桶存值的

我们用前缀异或和即可实现区间转化为数(满足区间减法即可

1n,m1e5,0k,值的大小1e5,

然后用莫队实现n sqrt(n),空间为o(值的大小)

操作:
分块排序,每次移动区间时

添加为存数并更新答案o(1)

删除为更新答案并删数o(1)


#include<bits/stdc++.h>
#define LL long long
#define IL inline
using namespace std;
const int N=100005;
int a[N],b[N];
int n,m,k;
struct modui{
    int l,r,id;
}q[N];
int cnt;
LL ans[N],ans0;
bool cmp(modui a,modui b){
    return a.l/cnt^b.l/cnt?a.l<b.l:a.r<b.r;
}
IL void add(int p){
    ans0+=b[a[p]^k];
    b[a[p]]++;
}
IL void del(int p){
    b[a[p]]--;
    ans0-=b[a[p]^k];
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    cnt=sqrt(n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++){
        a[i]^=a[i-1];
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d",&q[i].l,&q[i].r);
        q[i].l--;
        q[i].id=i;
    }
    sort(q+1,q+1+m,cmp);
    register int l=1,r=0;
    for(int i=1;i<=m;i++){
        while(l<q[i].l)del(l++);
        while(l>q[i].l)add(--l);
        while(r<q[i].r)add(++r);
        while(r>q[i].r)del(r--);
        ans[q[i].id]=ans0;
    }
    for(int i=1;i<=m;i++){
        printf("%lld\n",ans[i]);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/zrqlj/p/11507317.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值