题目链接

题意

区间两数异或在二进制下有 \(k\) 个 \(1\) 的对数。

Sol

普通莫队的话,如果要实时维护好区间内的答案需要支持区间对一个数求答案。

直接做不是很好做,容易发现其实这也就是一个区间询问。那么可以把莫队中要求的东西再次离线下来。

我们把上述询问拆成前缀相减的形式,这样我们要做到就是多次询问一个前缀对一个数的答案。

由于在数据范围下二进制下有 \(k\) 个 \(1\) 的数并不是太多,我们可以直接从前往后做,遇到一个数 \(x\) 则把 \(x\oplus number(k)\) 加入桶中 (\(number(k)\)表示二进制下有 \(k\) 个\(1\)的数)。当我们遇到一个询问 数 \(y\) 和当前前缀的答案时,只需要看 \(y\) 的桶被加入了多少个数就行了。

复杂度分析: 由于询问个数和莫队移动次数同阶,为 \(O(n\sqrt n)\) ,查询复杂度是 \(O(1)\) 的所以查询复杂度就是 \(O(n\sqrt n)\)。然后我们每加入一个数需要 最多\({14\choose 7}\)次插入操作,所以这部分复杂度为 \(O(n*{14\choose 7})\)。

愉快地提交上去后,就会 \(TLE+MLE\),因为这个复杂度还是比较紧的,而且询问个数 \(O(n\sqrt n)\) 全存下来的话会被卡空间。

怎么办呢?

发现有许多询问都是一个前缀和前缀后面那一个数的答案,这部分我们可以直接一开始预处理然后询问时直接贡献。省去存储一些询问,加快了速度。

但是这样还不够,再发现我们的另一种询问是对于一个固定的端点的询问一段区间内的数,我们可以只存一个询问。这样不仅省去了莫队时指针的移动复杂度,也省了空间,就可以过了。

code:

#include<bits/stdc++.h>
using namespace std;
#define Set(a,b) memset(a,b,sizeof(a))
template<class T>inline void init(T&x){
x=0;char ch=getchar();bool t=0;
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);
if(t) x=-x;return;
}typedef long long ll;
int n,m,k;
const int N=1e5+10;
int SIZE;
const int INF=16384;
int a[N],bl[N];ll ans[N];
struct query{
int l,r,id;
query(){l=r=id=0;}
query(int _l,int _r,int _id){l=_l,r=_r,id=_id;}
inline bool operator <(const query b)const{if(bl[l]!=bl[b.l]) return bl[l]<bl[b.l];else return r<b.r;}
}Que[N];
typedef pair<int,int> PA;
vector<query> PQ[N];
int number[3434];int numcnt=0;
#define lowbit(a) ((a)&(-a))
inline int Count(int x){int cnt=0;while(x) ++cnt,x^=lowbit(x);return cnt;}
int Pre[N],Bac[INF];ll S[N]; int main()
{
init(n),init(m),init(k);SIZE=sqrt(n);
for(int i=1;i<=n;++i) init(a[i]),bl[i]=(i-1+SIZE)/SIZE;
for(int i=0;i<INF;++i) if(Count(i)==k) number[++numcnt]=i; if(k>14) while(m--) puts("0");
else {
S[0]=0;
for(int i=1;i<=n;++i) {Pre[i]=Bac[a[i]];S[i]=S[i-1]+Pre[i];for(int j=1;j<=numcnt;++j) ++Bac[a[i]^number[j]];}S[n+1]=S[n];
Set(Bac,0);
for(int i=1;i<=m;++i) {init(Que[i].l),init(Que[i].r),Que[i].id=i;}sort(Que+1,Que+1+m);
int l=Que[1].l;int r=Que[1].l;
for(int i=1;i<=m;++i) {
const int ID=Que[i].id;
if(r<Que[i].r) {++r;ans[ID]+=S[Que[i].r]-S[r-1];PQ[l-1].emplace_back(query(r,Que[i].r,-ID));r=Que[i].r;}
if(l>Que[i].l) {--l;ans[ID]-=(S[l]-S[Que[i].l-1])+(int)(k==0)*(l-Que[i].l+1);PQ[r].emplace_back(query(Que[i].l,l,ID));l=Que[i].l;}
if(r>Que[i].r) {ans[ID]-=S[r]-S[Que[i].r];PQ[l-1].emplace_back(query(Que[i].r+1,r,ID));r=Que[i].r;}
if(l<Que[i].l) {ans[ID]+=S[Que[i].l-1]-S[l-1]+(int)(k==0)*(Que[i].l-l);PQ[r].emplace_back(query(l,Que[i].l-1,-ID));l=Que[i].l;}
}
Set(Bac,0);
for(int i=1;i<=n;++i) {
for(int j=1;j<=numcnt;++j) ++Bac[a[i]^number[j]];
for(query P:PQ[i]) {
int ID=abs(P.id),f=P.id/ID;
int l=P.l,r=P.r;ll res=0;
for(int j=l;j<=r;++j) res+=Bac[a[j]];
ans[ID]+=res*f;
}
}
for(int i=1;i<=m;++i) ans[Que[i].id]+=ans[Que[i-1].id];
for(int i=1;i<=m;++i) printf("%lld\n",ans[i]);
}
return 0;
}

【LuoguP4887】第十四分块(前体)的更多相关文章

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

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

  2. Luogu4887 第十四分块(前体)

    sto \(lxl\) orz 考虑莫队,每次移动端点,我们都要询问区间内和当前数字异或有 \(k\) 个 \(1\) 的数字个数 询问 \([l,r]\) 可以再次离线,拆成询问 \([1,l-1] ...

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

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

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

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

  5. 洛谷 P4887 -【模板】莫队二次离线(第十四分块(前体))(莫队二次离线)

    题面传送门 莫队二次离线 mol ban tea,大概是这道题让我第一次听说有这东西? 首先看到这类数数对的问题可以考虑莫队,记 \(S\) 为二进制下有 \(k\) 个 \(1\) 的数集,我们实时 ...

  6. 「kuangbin带你飞」专题十四 数论基础

    layout: post title: 「kuangbin带你飞」专题十四 数论基础 author: "luowentaoaa" catalog: true tags: mathj ...

  7. Alink漫谈(十四) :多层感知机 之 总体架构

    Alink漫谈(十四) :多层感知机 之 总体架构 目录 Alink漫谈(十四) :多层感知机 之 总体架构 0x00 摘要 0x01 背景概念 1.1 前馈神经网络 1.2 反向传播 1.3 代价函 ...

  8. 我的MYSQL学习心得(十四) 备份和恢复

    我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...

  9. 雅虎(yahoo)前端优化十四条军规

    第一条.尽可能的减少 HTTP 的请求数 (Make Fewer HTTP Requests ) http请求是要开销的,想办法减少请求数自然可以提高网页速度.常用的方法,合并css,js(将一个页面 ...

随机推荐

  1. fio 硬盘测试工具

    一.windows环境 1. 安装fio:http://www.bluestop.org/fio/ 可以选择不同版本的安装,安装后在C:\Program Files\fio目录中可以找到fio的执行程 ...

  2. 谈一谈 Normalize.css

    Normalize.css是一种CSS reset的替代方案.它在默认的HTML元素样式上提供了跨浏览器的高度一致性.相比于传统的CSS reset,Normalize.css是一种现代的.为HTML ...

  3. springboot_redis

    1.引入redis的启动器 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...

  4. 关于.Net Core+Angular+Ueditor富文本编辑器的使用方式

    博客:https://www.cnblogs.com/24klr/ 资料:https://www.jianshu.com/p/0b21a1324d47 GitHub:https://github.co ...

  5. mysql——修改表名、修改字段名、修改字段数据类型、增加字段、删除字段、修改字段排列位置、修改存储引擎、删除表 (示例)

    一.创建表和插入数据: ), mz ), bz ) ); ,'sww','sww01'); ,'aww','aww02'); ,'qww','qww03'), (,'eww','eww04'), (, ...

  6. 动态赋予java类的属性set与get值

    public class Contact { private String name; private String tel; private attrControl attrC=new attrCo ...

  7. Java内存模型 (一)什么是进程?什么是线程?进程和线程之间的区别是什么?

    什么是进程?什么是线程? 进程是系统中正在运行的一个程序,程序一旦运行就是进程. 进程可以看成程序执行的一个实例.进程是系统资源分配的独立实体,每个进程都拥有独立的地址空间.一个进程无法访问另一个进程 ...

  8. python smtplib server not connect

    最近发现用smtplib发邮件一直发送不成功,使用debug发现前面都正常,但是DATA发送直接被smtp服务器直接断开.smtp服务器显示body丢失. 后来发现是我加了附件,有指定文件类型: at ...

  9. java 统计素数个数问题

    题目:判断101-200之间有多少个素数,并输出所有素数. 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数. package Study ...

  10. Threadlocal线程本地变量理解

    转载:https://www.cnblogs.com/chengxiao/p/6152824.html 总结: 作用:ThreadLocal 线程本地变量,可用于分布式项目的日志追踪 用法:在切面中生 ...