zoukankan      html  css  js  c++  java
  • BZOJ5301: [Cqoi2018]异或序列

    BZOJ5301: [Cqoi2018]异或序列

    Description

    已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l、r ,问在 [l,r] 区间内,有多少连续子序列满足异或和等于 k 。
    也就是说,对于所有的 x,y (l≤x≤y≤r),能够满足a[x]^a[x+1]^…^a[y]=k的x,y有多少组。

    Input

    输入文件第一行,为3个整数n,m,k。
    第二行为空格分开的n个整数,即ai,a2,….an。
    接下来m行,每行两个整数lj,rj,表示一次查询。
    1≤n,m≤105,O≤k,ai≤105,1≤lj≤rj≤n

    Output

    输出文件共m行,对应每个查询的计算结果。

    Sample Input

    4 5 1
    1 2 3 1
    1 4
    1 3
    2 3
    2 4
    4 4

    Sample Output

    4
    2
    1
    2
    1

    题解Here!
    又是区间题,又没有强制在线。。。
    去吧莫队!
    预处理异或前缀和,每次莫队暴力转移就好。

    但是这道题需要注意一下左端点的转移。

    如果原数组是$val[l]$,前缀和数组是$sum[l]$的话。

    因为$val[l]=sum[l] xor sum[l-1]$,所以我们删除l的时候,实际上需要删除的是$l-1$。

    剩下的就是莫队板子了。

    据说是$CF$原题?反正我从来不做$CF$题。。。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #define MAXN 100010
    using namespace std;
    int n,m,k,block,s=0;
    int val[MAXN],sum[MAXN],num[MAXN],ans[MAXN];
    struct Question{
        int l,r,id;
    }que[MAXN];
    inline int read(){
        int date=0,w=1;char c=0;
        while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
        while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
        return date*w;
    }
    inline bool cmp(const Question &p,const Question &q){
        return (p.l/block==q.l/block?((p.l/block)&1?p.r<q.r:p.r>q.r):p.l<q.l);
    }
    inline void change_add(int v){s+=num[v^k];num[v]++;}
    inline void change_del(int v){num[v]--;s-=num[v^k];}
    void work(){
        int left=1,right=0;
        num[0]=1;
        for(int i=1;i<=m;i++){
            while(que[i].l<left){left--;change_add(sum[left-1]);}
            while(que[i].l>left){change_del(sum[left-1]);left++;}
            while(que[i].r<right)change_del(sum[right--]);
            while(que[i].r>right)change_add(sum[++right]);
            ans[que[i].id]=s;
        }
        for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
    }
    void init(){
        n=read();m=read();k=read();
        sum[0]=0;
        for(int i=1;i<=n;i++){
            int x=read();
            sum[i]=sum[i-1]^x;
        }
        block=sqrt(n);
        for(int i=1;i<=m;i++){
            que[i].l=read();que[i].r=read();
            que[i].id=i;
        }
        sort(que+1,que+m+1,cmp);
    }
    int main(){
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    设计模式之代理模式
    Java面试总结系列之Collections.sort()
    Scala基础
    Win7 电脑设置临时网络,无法加入网络;internet禁止网络共享
    Java面试题系列 提高Java I/O 性能
    电子商务中:B2C、B2B、C2B、C2C、O2O、P2P
    JVM内存格局总结
    Dubbo相关博文整理
    Java面试题汇总(一)
    Java多线程总结
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9470904.html
Copyright © 2011-2022 走看看