Luogu P4462 [CQOI2018]异或序列

一道稍微要点脑子的莫队题,原来省选也会搬CF原题

首先利用\(xor\)的性质,我们可以搞一个异或前缀和的东西

每一次插入一个数,考虑它和之前已经加入的数能产生多少贡献

记一下之前的异或总值,然后还是利用异或的性质再异或一遍

这个我们再开一个数据统计一下出现次数

但是唯一要注意的就是一些细节问题,尤其是左端点加入(or删除)的时候要减一

然后就可以水过了(我的代码莫队的时候写的有点骚)

CODE

#include<cstdio>
#include<cctype>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=100005;
struct data
{
    int l,r,id; long long ans;
}q[N];
int a[N],n,m,k,size,tot,blk[N],L,R,sum[N],cnt[N<<1]={1};
long long res;
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch; while (!isdigit(ch=tc()));
    while (x=(x<<3)+(x<<1)+ch-‘0‘,isdigit(ch=tc()));
}
inline void write(int x)
{
    if (x>9) write(x/10);
    putchar(x%10+‘0‘);
}
inline bool cmp1(data a,data b)
{
    return blk[a.l]<blk[b.l]||(blk[a.l]==blk[b.l]&&(blk[a.l]&1?a.r<b.r:a.r>b.r));
}
inline bool cmp2(data a,data b)
{
    return a.id<b.id;
}
inline void add(int x)
{
    res+=cnt[k^sum[x]]; ++cnt[sum[x]];
}
inline void del(int x)
{
    --cnt[sum[x]]; res-=cnt[k^sum[x]];
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    register int i; read(n); read(m); read(k); size=sqrt(n);
    for (i=1;i<=n;++i) read(a[i]),blk[i]=(i-1)/size+1,sum[i]=sum[i-1]^a[i];
    for (i=1;i<=m;++i) read(q[i].l),read(q[i].r),q[i].id=i;
    sort(q+1,q+m+1,cmp1); L=1; R=0;
    for (i=1;i<=m;++i)
    {
        while (L>q[i].l) add(--L-1); while (L<q[i].l) del(-1+L++);
        while (R<q[i].r) add(++R); while (R>q[i].r) del(R--);
        q[i].ans=res;
    }
    for (sort(q+1,q+m+1,cmp2),i=1;i<=m;++i) write(q[i].ans),putchar(‘\n‘);
    return 0;
}

原文地址:https://www.cnblogs.com/cjjsb/p/9557242.html

时间: 2024-09-29 07:08:04

Luogu P4462 [CQOI2018]异或序列的相关文章

P4462 [CQOI2018]异或序列

题目描述 已知一个长度为n的整数数列 a1,a2,...,ana_1,a_2,...,a_na1?,a2?,...,an? ,给定查询参数l.r,问在 al,al+1,...,ara_l,a_{l+1},...,a_ral?,al+1?,...,ar? 区间内,有多少子序列满足异或和等于k.也就是说,对于所有的x,y (I ≤ x ≤ y ≤ r),能够满足 ax?ax+1?...?ay=ka_x \bigoplus a_{x+1} \bigoplus ... \bigoplus a_y = k

P4462 [CQOI2018]异或序列 莫队 异或

题目描述 已知一个长度为n的整数数列a_1,a_2,...,a_na1?,a2?,...,an?,给定查询参数l.r,问在a_l,a_{l+1},...,a_ral?,al+1?,...,ar?区间内,有多少子串满足异或和等于k.也就是说,对于所有的x,y (I ≤ x ≤ y ≤ r),能够满足a_x \bigoplus a_{x+1} \bigoplus ... \bigoplus a_y = kax??ax+1??...?ay?=k的x,y有多少组. 输入格式 输入文件第一行,为3个整数n

P4462 [CQOI2018]异或序列 莫队

题意:给定数列 \(a\) 和 \(k\) ,询问区间 \([l,r]\) 中有多少子区间满足异或和为 \(k\). 莫队.我们可以记录前缀异或值 \(a_i\),修改时,贡献为 \(c[a_i\bigoplus k]\) . #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #define R register in

「luogu4462」[CQOI2018]异或序列

「luogu4462」[CQOI2018]异或序列 一句话题意 输入 \(n\) 个数,给定\(k\),共 \(m\) 组询问,输出第 \(i\) 组询问 \(l_i\) \(r_i\) 中有多少个连续子序列的异或和等于 \(k\).数据范围均在 \([0,1e5]\). 本题不强制在线,故莫队. 记序列 \(a\) 的前缀异或和 \(pre\),用一个桶 \(t_i\) 记录当前查询区间内前缀异或和为 \(i\) 的数量. 代码如下: #include <cstdio> #include &

[LuoguP4462][CQOI2018]异或序列

闲话 这是一篇 在线算法 的题解!!! 用了分块,虽然比莫队差一点点点点,但怎么说也是一种优美的解法. 只是比较考验细节,调了好几个小时啊啊啊啊啊... wtcl... 正片 数列分块的思想(熟悉的可以略过) 数列分块又被称作数列的平方分割. 数列分块是将整段数列分为均匀的几块,使得每块长度为\(b\)(末块的最后一个是第\(n\)个,并不是直接向后\(+b\)个,注意特判).这里,\(b\)常取\(\sqrt{n}\). 然后对每个块都维护一些必要的信息. 比如:P3372 [模板]线段树 1

[CQOI2018] 异或序列

题目链接:戳我 哈哈哈我竟然秒切了省选题 莫队+异或. 考虑异或的性质,一个数同时异或两次等于没有进行操作.那么我们设a[i]为前i个数的异或和,显然对于一个区间\([l,now]\),\(a[l-1]\oplus a[now]\)就是这个区间里面所有的数的异或和.如果\(a[l-1]\oplus a[now]=k\)那么ans++,这等同于\(a[l-1]=k\oplus a[now]\). 代码如下: #include<iostream> #include<cstdio> #i

[CQOI2018]异或序列 题解

转化题意: 给n个整数,给一个值k,m个询问,每个询问给出一个区间,求区间里有多少对数异或为k 注意到n个整数的值比较小,可以用桶存值的 我们用前缀异或和即可实现区间转化为数(满足区间减法即可 1≤n,m≤1e5,0≤k,值的大小≤1e5, 然后用莫队实现n sqrt(n),空间为o(值的大小) 操作:分块排序,每次移动区间时 添加为存数并更新答案o(1) 删除为更新答案并删数o(1) #include<bits/stdc++.h> #define LL long long #define I

CQOI2018异或序列 [莫队]

莫队板子 用于复习 #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <map> #define Sqr(x) ((x)*(x)) using namespace std; const int N = 1e5 + 5; struct Q{ int x, y, id; }q[N];

[Luogu P4735]最大异或和(可持久化Trie)

[Luogu P4735]最大异或和(可持久化Trie) 题面 给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类型: 1.Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1. 2.Qlrx:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少. 分析 维护\(sum[i]=sum[i-1] \ \text{XOR} \ a[i]\),那么答案就是\(sum[