zoukankan      html  css  js  c++  java
  • 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

    Solution

    不能再这么颓下去了
    昨天打了一天板子感觉现在脑子锈了QAQ……
    题意杀了好久……明明子序列应该是不连续的
    一看题目这个形式基本莫队没跑了,
    然而如果两端加入/减掉一个数,这个数对于区间的影响是靠近它的连续一段
    这显然是没法维护的。所以可以维护一个异或前缀和sum
    因为a[x] xor a[x+1]……xor a[y-1] xor a[y] 等价于 sum[y] xor sum[x-1]
    那么我们就可以用莫队来维护前缀和了。
    每次往莫队里加入/删除前缀和的时候只需要考虑有多少个数与当前数异或等于k,开个桶即可。
    因为查询区间[x,y]的时候我们需要sum[x-1]~sum[y],所以读入的时候左端点要减一。

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 #define N (500000+100)
     7 using namespace std;
     8 
     9 struct node{int x,y,num,id,ans;}ask[N];
    10 int Keg[N],sum[N],n,m,k,x,now;
    11 
    12 bool cmp1(node a,node b){return a.id==b.id?a.y<b.y:a.id<b.id;}
    13 bool cmp2(node a,node b){return a.num<b.num;}
    14 
    15 void Ins(int pos){now+=Keg[sum[pos]^k];    Keg[sum[pos]]++;}
    16 void Del(int pos){Keg[sum[pos]]--; now-=Keg[sum[pos]^k];}
    17 
    18 int main()
    19 {
    20     scanf("%d%d%d",&n,&m,&k);
    21     int unit=sqrt(n);
    22     for (int i=1; i<=n; ++i)
    23         scanf("%d",&x),sum[i]=sum[i-1]^x;
    24     for (int i=1; i<=m; ++i)
    25     {
    26         scanf("%d%d",&ask[i].x,&ask[i].y);
    27         ask[i].x--; ask[i].num=i;
    28          ask[i].id=ask[i].x/unit;
    29     }
    30     sort(ask+1,ask+m+1,cmp1);
    31     
    32     int l=1,r=0;
    33     for (int i=1; i<=m; ++i)
    34     {
    35         while (l<ask[i].x) Del(l++);
    36         while (l>ask[i].x) Ins(--l);
    37         while (r<ask[i].y) Ins(++r);
    38         while (r>ask[i].y) Del(r--);
    39         ask[i].ans=now;
    40     }
    41     
    42     sort(ask+1,ask+m+1,cmp2);
    43     for (int i=1; i<=m; ++i)
    44         printf("%d
    ",ask[i].ans);
    45 }
  • 相关阅读:
    leetcode 137
    leetcode 134
    133. Clone Graph
    leetcode 131
    leetcode 130
    mac uwsgi ssl issue handler
    leetcode 85 Maximal Rectangle golang
    leetcode 84 golang
    leetcode 61
    C# 后台实现一次上传多个文件
  • 原文地址:https://www.cnblogs.com/refun/p/8931154.html
Copyright © 2011-2022 走看看