题目链接

题意

区间两数异或在二进制下有 \(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. Durable NAND flash memory management

    词条积累 1.NAND flash memory http://www.searchstorage.com.cn/whatis/word_6052.htm http://baike.baidu.com ...

  2. 菜鸟系列Fabric——Fabric 网络架构介绍(4)

    Fabric 网络架构介绍 1. 网络架构介绍 如图所示,fabric网络架构主要包含客户端节点.CA节点.Peer节点.Orderer节点这几个部分.并且fabric架构是安装组织来进行划分当,每个 ...

  3. springmvc默认配置文件

    当在新建的maven web项目的web.xml中直接加入下面的<servlet>和<servlet-mapping>后,直接运行就会出现这个报错,意思就是找不到默认的spri ...

  4. linux 使用tmux

    一. 什么是tmux 1.1. tmux 是两个单词的缩写,即“Terminal MultipleXer”,意思是“终端复用器“ 1.2. tmux 结构 1.2.1. tmux主要由三层: < ...

  5. IO库中的宽字符语言

    wchar_t是C/C++的字符类型,是一种扩展的存储方式.wchar_t类型主要用在国际化程序的实现中,但它不等同于uni编码.uni编码的字符一般以wchar_t类型存. IO库为了支持宽字符语言 ...

  6. kaggle笔记

    roc曲线介绍:https://www.cnblogs.com/dlml/p/4403482.html one-hot encode: 1) Drop Categorical Variables 2) ...

  7. GitHub从小白到熟悉<四>

    GitHub issue 使用教程 创建 一个issue  (显示所有bug 或者 说 交流的 问题列表)

  8. 安装docker私有仓库

    先安装docker:http://www.cnblogs.com/cjsblogs/p/8717304.html 安装私有仓库 #下载registry docker pull registry #制作 ...

  9. Linq Distinct 自定义比较

    private class MyMenuComparer : IEqualityComparer { public bool Equals(ParMenu x, ParMenu y){ return ...

  10. CF407D Largest Submatrix 3

    cf luogu 被自己菜到自闭了/kk 既然是子矩阵,那么惯用套路为枚举矩阵上下边界,然后\(O(n)\)扫描求解.这题里要从左往右枚举右端点,然后看左端点最多能放到哪,那就对于每个数求出在上下边界 ...