题面传送门

莫队二次离线 mol ban tea,大概是这道题让我第一次听说有这东西?

首先看到这类数数对的问题可以考虑莫队,记 \(S\) 为二进制下有 \(k\) 个 \(1\) 的数集,我们实时维护一个桶 \(cnt_i\) 表示当前区间中值为 \(i\) 的数有多少个,那么加入一个数 \(v\) 的时候,答案会增加 \(\sum\limits_{y\in S}cnt_{y\oplus v}\),这样暴力莫队复杂度是 \(n\sqrt{n}\dbinom{14}{k}\),如果你过了我请你吃糖

考虑优化,我们记 \(f(x,l,r)\) 表示当前区间为 \([l,r]\),加入 \(a_x\) 后答案的增量,记 \(\sum\limits_{y\in S}cnt_{y\oplus a_x}\)。考虑莫队中每个端点的移动对答案的贡献,我们以右端点为例,设右端点由 \(r\) 移动到了 \(r'\),这里我们不妨设 \(r'>r\),\(r'<r\) 的情况也同理,那么答案显然会增加 \(\sum\limits_{i=r+1}^{r'}f(i,l,i-1)\),这东西不太好直接求,考虑用差分的思想,将这东西拆成 \(f(i,1,i-1)-f(i,1,l-1)\),那么 \(\Delta=\sum\limits_{i=r+1}^{r'}f(i,1,i-1)-\sum\limits_{i=r+1}^{r'}f(i,1,l-1)\),不难发现第一个 \(\sum\) 里的东西只与 \(i\) 有关,我们可以预处理 \(f(i,1,i-1)\) 的前缀和即可 \(\mathcal O(1)\) 求出,至于怎么求 \(f(i,1,i-1)\)……这个看不出来就有点【数据删除】了罢,就从左往右扫一遍并实时维护一个桶 \(cnt\),扫到 \(a_i\) 的时候 \(f(i,1,i-1)\) 的值就是当时 \(\sum\limits_{x\in S}cnt_{x\oplus a_i}\)。后面那坨东西在线求出不太容易,不过既然叫“莫队二次离线”那就离线一下呗,不难发现所有这样的东西都可以用一个三元组 \((x,l,r)\) 表示 \(\sum\limits_{i=l}^rf(i,1,x)\),我们将这样的询问都挂在 \(x\) 上然后从左往右扫描一遍,还是实时维护一个桶 \(cnt\),不过这时候 \(cnt_v\) 的含义为 \([1,i]\) 中有多少个数 \(j\) 满足 \(v\oplus a_j\in S\),这显然可以在 \(\mathcal O(n\dbinom{14}{k})\) 的时间内求出,然后每遇到一个询问 \((i,l,r)\),就暴力枚举 \(t\in[l,r]\) 并令贡献加上/减去 \(cnt_{a_t}\),由于莫队指针移动的总距离为 \(n\sqrt{n}\) 级别的,因此这里的 \(\sum r-l+1\) 也是 \(n\sqrt{n}\) 级别的,可以通过。

上文所叙述的都是右端点移动的情况,左端点移动的情况大体上也差不多,还是设左端点由 \(l\) 移动到了 \(l'\),\(l'<l\)那么答案的增量就是 \(\sum\limits_{i=l'}^{l-1}f(i,i+1,r)\),这里有一个小小的区别就是不能差分前缀和,而要差分后缀和,即 \(f(i,i+1,r)=f(i,i+1,n)-f(i,r+1,n)\),这两项都可以用类似的方式维护。

最后,由于我们求出的是每次莫队后答案的增量,还需对每次询问的结果求一遍前缀和即可得到每次询问真正的答案。

时间复杂度 \(n\sqrt{n}+n\dbinom{14}{k}\)

最后总结一下莫队二次离线的适用范围:

  • 可以莫队
  • 更新答案的时间不是 \(\mathcal O(1)\)(一个数对答案的贡献与区间中别的数有关,例如比一个数小的数有多少,即 P5501)
const int MAXN=1e5;
const int MAXV=1<<14;
int n,qu,k,a[MAXN+5],blk_sz,blk_cnt;
int bel[MAXN+5],L[MAXN+5],R[MAXN+5];
ll pre[MAXN+5],suf[MAXN+5],anss[MAXN+5];
int buc[MAXV+5];
struct query{
int l,r,id;ll ans;
bool operator <(const query &rhs) const{
if(bel[l]^bel[rhs.l]) return bel[l]<bel[rhs.l];
else if(bel[l]&1) return r<rhs.r;
else return r>rhs.r;
}
} q[MAXN+5];
struct qwq{int l,r,id,op;};
vector<qwq> vl[MAXN+5],vr[MAXN+5];
int main(){
scanf("%d%d%d",&n,&qu,&k);vector<int> v;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=0;i<MAXV;i++) if(__builtin_popcount(i)==k) v.pb(i);
blk_sz=(int)pow(n,0.5);blk_cnt=(n-1)/blk_sz+1;
for(int i=1;i<=blk_cnt;i++){
L[i]=(i-1)*blk_sz+1;R[i]=min(i*blk_sz,n);
for(int j=L[i];j<=R[i];j++) bel[j]=i;
}
for(int i=1;i<=qu;i++) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
sort(q+1,q+qu+1);int cl=1,cr=0;
for(int i=1;i<=n;i++){
pre[i]=pre[i-1];
for(int j:v) pre[i]+=buc[j^a[i]];
buc[a[i]]++;
} memset(buc,0,sizeof(buc));
for(int i=n;i;i--){
suf[i]=suf[i+1];
for(int j:v) suf[i]+=buc[j^a[i]];
buc[a[i]]++;
}
for(int i=1;i<=qu;i++){
q[i].ans=pre[q[i].r]-pre[cr]+suf[q[i].l]-suf[cl];
if(cl<q[i].l) vr[cr+1].pb({cl,q[i].l-1,i,1});
if(cl>q[i].l) vr[cr+1].pb({q[i].l,cl-1,i,-1});
if(cr<q[i].r) vl[q[i].l-1].pb({cr+1,q[i].r,i,-1});
if(cr>q[i].r) vl[q[i].l-1].pb({q[i].r+1,cr,i,1});
cl=q[i].l;cr=q[i].r;
} memset(buc,0,sizeof(buc));
for(int i=1;i<=n;i++){
for(int j:v) buc[a[i]^j]++;
for(int j=0;j<vl[i].size();j++){
int l=vl[i][j].l,r=vl[i][j].r,id=vl[i][j].id;
ll sum=0;for(int t=l;t<=r;t++) sum+=buc[a[t]];
q[id].ans+=sum*vl[i][j].op;
}
} memset(buc,0,sizeof(buc));
for(int i=n;i;i--){
for(int j:v) buc[a[i]^j]++;
for(int j=0;j<vr[i].size();j++){
int l=vr[i][j].l,r=vr[i][j].r,id=vr[i][j].id;
ll sum=0;for(int t=l;t<=r;t++) sum+=buc[a[t]];
q[id].ans+=sum*vr[i][j].op;
}
}
for(int i=2;i<=qu;i++) q[i].ans+=q[i-1].ans;
for(int i=1;i<=qu;i++) anss[q[i].id]=q[i].ans;
for(int i=1;i<=qu;i++) printf("%lld\n",anss[i]);
return 0;
}
/*
6 1 0
1 2 3 1 2 3
1 6 6 5 1
1 2 3 4 5 6
1 5
1 6
2 5
2 6
3 6 14 5 1
1 2 3 4 5 6 7 1 2 3 4 5 6 7
1 14
2 13
3 9
1 12
4 11
*/

洛谷 P4887 -【模板】莫队二次离线(第十四分块(前体))(莫队二次离线)的更多相关文章

  1. P4887 第十四分块(前体) 莫队

    题意: 给你一个序列,每次询问l,r问多少个a[i]^a[j]有k个1,k固定. 序列长度1e5,a[i]<=2^14 时限1s,空间40M 题解: 个人其实开始没什么思路,看了题解也好久,题解 ...

  2. 洛谷P4887 第十四分块(前体)(二次离线莫队)

    题面 传送门 题解 lxl大毒瘤 我们考虑莫队,在移动端点的时候相当于我们需要快速计算一个区间内和当前数字异或和中\(1\)的个数为\(k\)的数有几个,而这个显然是可以差分的,也就是\([l,r]\ ...

  3. [洛谷P4887]第十四分块(前体)

    题目大意: 给定一个长度为\(n\)的序列\(a\),\(k\),和\(m\)次询问. 每次询问给定区间\([l,r]\),求满足\(l\leqslant i< j\leqslant r\)且\ ...

  4. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  5. 洛谷-P5357-【模板】AC自动机(二次加强版)

    题目传送门 -------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题 sol:AC自动机,还是要解决跳fail边产生的重复访问,但 ...

  6. 洛谷P3375 [模板]KMP字符串匹配

    To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...

  7. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  8. 【AC自动机】洛谷三道模板题

    [题目链接] https://www.luogu.org/problem/P3808 [题意] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. [题解] 不再介绍基础知识了,就是裸的模 ...

  9. 洛谷.1919.[模板]A*B Problem升级版(FFT)

    题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 ...

随机推荐

  1. (课内)信安数基RSA-level3-5

    emmmm感觉其实自己对这个的理解完全不够,原理只能写出这么个东西(悲) 代码完全是 攻击方式中(1)(2)内容的实现. lambda是一种可以理解为匿名函数的写法:写在这里看起来很酷炫(bushi) ...

  2. $dy$讲课总结

    字符串: 1.广义后缀自动机(大小为\(m\))上跑一个长度为\(n\)的串,所有匹配位置及在\(parent\)树上其祖先的数量的和为\(min(n^2,m)\),单次最劣是\(O(m)\). 但是 ...

  3. CSP/S 2020 退役记

    上一次的AFO记 上上次的AFO记 Day -INF 一条咸鱼的垂死挣扎. RP+=INF Day 0 出发辣. 早上来到机房,带上了准备的面包和泡面....然而后来嫌太占地方就没拿...草了. 而且 ...

  4. 数列极限计算中运用皮亚诺Taylor展开巧解

    这是讲义里比较精华的几个题目,今晚翻看也是想到了,总结出来(处理k/n2形式). 推广式子如下: 例题如下:

  5. 你一定不知道的Unsafe用法

    Unsafe是什么 首先我们说Unsafe类位于rt.jar里面sun.misc包下面,Unsafe翻译过来是不安全的,这倒不是说这个类是不安全的,而是说开发人员使用Unsafe是不安全的,也就是不推 ...

  6. Linux上Qt旋转显示

    对于嵌入式设备来说用于显示的LCD总是千奇百怪,比如说明明是一个竖屏,但是客户却要当横屏使用,也就是意味着我们需要将整个屏幕上显示的内容旋转90度或者270度. 这个操作对于Android系统来说相当 ...

  7. python mysqlclient安装失败 Command "python setup.py egg_info" failed with error code 1

    python2 python3 中代码 pip install mysqlclient 都安装失败的话, 很有可能是你的操作系统中没有安装mysql 如果确定已经安装了,请忽略下面的内容. Ubunt ...

  8. Downward API —— 在容器内部获取 Pod 信息

    我们知道,每个 Pod 在被超过创建出来之后,都会被系统分配唯一的名字.IP地址,并且处于某个 Namespace 中,那么我们如何在 Pod 的容器内获取 Pod 的这些重要信息呢? 答案就是使用 ...

  9. 浅谈对typora的使用

    内容概要 - 什么是typora - typora的具体使用 目录 内容概要 - 什么是typora - typora的具体使用 1. 什么是typora 2.typora的具体使用 1.标题级别 2 ...

  10. rocketmq有序消息的(四)

    opic的有序消息已经成为mq的标配.而RocketMQ中是这样区分消息类型的, 普通消息也叫做无序消息,简单来说就是没有顺序的消息,而有序消息就是按照一定的先后顺序的消息类型.举个例子,produc ...