题面传送门

莫队二次离线 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. 耗时一个月,整理出这份Hadoop吐血宝典

    本文目录: 一.HDFS 二.MapReduce 三.Yarn 四.Hadoop3.x 新特性 五.Hadoop 大厂面试真题解析 Hadoop 涉及的知识点如下图所示,本文将逐一讲解: 本文档参考了 ...

  2. TStor-OneCOS ,主打专一海量对象场景

    ​谁能与你厮守终身 生活在21世纪,最常见的事莫过于更新换代了,找一款能长久适用的产品,是很多人都希望拥有的,特别是针对于云服务产品,而对象·混合云存储新增 TStor-OneCOS 就是这样一款可以 ...

  3. [no code][scrum meeting] Alpha 9

    项目 内容 会议时间 2020-04-15 会议主题 OCR验收 会议时长 15min 参会人员 OCR组成员 $( "#cnblogs_post_body" ).catalog( ...

  4. OO--第三单元规格化设计 博客作业

    OO--第三单元规格化设计 博客作业 前言 第三单元,我们以JML为基础,先后完成了 PathContainer -> Graph -> RailwaySystem 这是一个递进的过程,代 ...

  5. Noip模拟41 2021.8.16

    T1 你相信引力吗 对于区间的大小关系问题,往往使用单调栈来解决 这道题的优弧和劣弧很烦,考虑将其等价的转化 由于所有的合法情况绕过的弧都不会经过最高的冰锥, 又因为环可以任意亲定起点,这样可以直接把 ...

  6. AXI总线简介、ID分析、DMA、Vivado烧录、系统集成

    转载:https://blog.csdn.net/CrazyUncle/article/details/89918030?depth_1-utm_source=distribute.pc_releva ...

  7. hdu 1083 Courses(二分图最大匹配)

    题意: P门课,N个学生.     (1<=P<=100    1<=N<=300) 每门课有若干个学生可以成为这门课的代表(即候选人). 又规定每个学生最多只能成为一门课的代 ...

  8. 第35篇-方法调用指令之invokespecial与invokestatic

    这一篇将详细介绍invokespecial和invokestatic字节码指令的汇编实现逻辑 1.invokespecial指令 invokespecial指令的模板定义如下: def(Bytecod ...

  9. Centos7上安装Ubuntu容器

    1.再次之前我们要先装好docker,在上一篇我已经给出了教程,没有安装好的快去看看吧! 2.这里我们使用的是linux系统,所有在线安装是最简便的方法了.我们可以从国内拉取dockerhub镜像,这 ...

  10. Go语言核心36讲(Go语言进阶技术十四)--学习笔记

    20 | 错误处理 (下) 在上一篇文章中,我们主要讨论的是从使用者的角度看"怎样处理好错误值".那么,接下来我们需要关注的,就是站在建造者的角度,去关心"怎样才能给予使 ...