zoukankan      html  css  js  c++  java
  • [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
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    让他人变得优秀是伟大
    年龄越大,离家越远
    秋天的叶子
    [短彩信]C#短彩信模块开发设计(2)——配置
    jquery实现网页二级菜单简单代码
    HTML页面做中间页跳转传递参数
    ToJson
    Button页面中的按钮
    SQLSERVER 18056 错误
    在桌面添加可拖动/点击的悬浮窗口
  • 原文地址:https://www.cnblogs.com/zrqlj/p/11507317.html
Copyright © 2011-2022 走看看