【LuoguP4887】第十四分块(前体)
题意
区间两数异或在二进制下有 \(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】第十四分块(前体)的更多相关文章
- P4887 第十四分块(前体) 莫队
题意: 给你一个序列,每次询问l,r问多少个a[i]^a[j]有k个1,k固定. 序列长度1e5,a[i]<=2^14 时限1s,空间40M 题解: 个人其实开始没什么思路,看了题解也好久,题解 ...
- Luogu4887 第十四分块(前体)
sto \(lxl\) orz 考虑莫队,每次移动端点,我们都要询问区间内和当前数字异或有 \(k\) 个 \(1\) 的数字个数 询问 \([l,r]\) 可以再次离线,拆成询问 \([1,l-1] ...
- 洛谷P4887 第十四分块(前体)(二次离线莫队)
题面 传送门 题解 lxl大毒瘤 我们考虑莫队,在移动端点的时候相当于我们需要快速计算一个区间内和当前数字异或和中\(1\)的个数为\(k\)的数有几个,而这个显然是可以差分的,也就是\([l,r]\ ...
- [洛谷P4887]第十四分块(前体)
题目大意: 给定一个长度为\(n\)的序列\(a\),\(k\),和\(m\)次询问. 每次询问给定区间\([l,r]\),求满足\(l\leqslant i< j\leqslant r\)且\ ...
- 洛谷 P4887 -【模板】莫队二次离线(第十四分块(前体))(莫队二次离线)
题面传送门 莫队二次离线 mol ban tea,大概是这道题让我第一次听说有这东西? 首先看到这类数数对的问题可以考虑莫队,记 \(S\) 为二进制下有 \(k\) 个 \(1\) 的数集,我们实时 ...
- 「kuangbin带你飞」专题十四 数论基础
layout: post title: 「kuangbin带你飞」专题十四 数论基础 author: "luowentaoaa" catalog: true tags: mathj ...
- Alink漫谈(十四) :多层感知机 之 总体架构
Alink漫谈(十四) :多层感知机 之 总体架构 目录 Alink漫谈(十四) :多层感知机 之 总体架构 0x00 摘要 0x01 背景概念 1.1 前馈神经网络 1.2 反向传播 1.3 代价函 ...
- 我的MYSQL学习心得(十四) 备份和恢复
我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...
- 雅虎(yahoo)前端优化十四条军规
第一条.尽可能的减少 HTTP 的请求数 (Make Fewer HTTP Requests ) http请求是要开销的,想办法减少请求数自然可以提高网页速度.常用的方法,合并css,js(将一个页面 ...
随机推荐
- HCL试验9
PC1配置: ip:192.168.1.1 掩码:255.255.255.0 网关:192.168.1.254 上路由器配置: sys int gi0/0 ip add 192.168.100.10 ...
- 【Linux开发】linux设备驱动归纳总结(十):1.udev&misc
linux设备驱动归纳总结(十):1.udev&misc xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- SolidWorks学习笔记7 镜像,阵列
镜像 将特征,面,实体相对于一个平面来复制.修改原来的特征,镜像特征随之改变 阵列 线性阵列 , 在左侧,先激活要阵列的特征,然后点击小柱 然后选择方向1和方向2,该方向的阵列距离和数量(一般使用边线 ...
- C#追加日志文件
追加日志文件 using System; using System.IO; class DirAppend { public static void Main() { using (StreamWri ...
- MVVM 和 VUE三要素:响应式、模板引擎、渲染
MVVM 和 VUE三要素:响应式.模板引擎.渲染:https://blog.csdn.net/weixin_37644989/article/details/94409430
- 小白学习django第四站-关联数据库
使用mysql连接django首先要配置好相关环境 首先在setting.py配置数据库信息(需要现在mysql中创建一个数据库) 在setting.py那个目录的__init__.py文件中写入 之 ...
- 华为wlan配置流程及相关重要步骤AC配置
本次介绍是AC+fitAP组网方式的重要步骤. 一.基础配置 1.规划好ac+ap的组网方式和转发方式.(本次以三层旁挂直接转发),规划管理vlan,业务vlan,与AC连接的vlan,以及他们接口的 ...
- Java后端技术面试汇总(第二套)
1.Java相关 • Arraylist与LinkedList默认空间是多少:• Arraylist与LinkedList区别与各自的优势List 和 Map 区别:• 谈谈HashMap,哈希表解决 ...
- 基于CentOS系统部署EPICS环境
1.虚拟机安装CentOS系统2.打开终端,以root账户登录3.进入/usr/local目录下,新建文件夹epics,并进入该文件夹4.在/usr/local/epics目录下,执行wget htt ...
- 异常-finally关键字的特点及作用
package cn.itcast_07; import java.text.ParseException; import java.text.SimpleDateFormat; import jav ...