题目链接

题意

区间两数异或在二进制下有 \(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. 菜鸟系列Fabric——Fabric 网络架构介绍(4)

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

  2. Xtrabackup innobackupex

    Xtrabackup是由percona提供的mysql数据库备份工具,据官方介绍,这也是世界上惟一一款开源的能够对innodb和xtradb数据库进行热备的工. Xtrabackup中主要包含两个工具 ...

  3. HDU - 1711 A - Number Sequence(kmp

    HDU - 1711 A - Number Sequence   Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1 ...

  4. linux_文本编译使用命令

    一:字符模式与shell命令 字符界面和图形界面 字符界面优点: 1):系统执行效率高,稳定性高,执行结果可直接返回 2):节省系统资源,对一个服务器至关重要 3):节省大量网络开销,大幅降低运行成本 ...

  5. Codeforces 1201D. Treasure Hunting

    传送门 看一眼感觉就是 $dp$,但是似乎状态太多了 考虑推推性质 首先每到一行都要把所有宝藏都走到,那么一定会走到最左边的和最右边的宝藏 注意到一旦走完所有宝藏时肯定是在最左边或者最右边的宝藏位置 ...

  6. Mysql学习(三)之数据库管理工具Navicat

    前言 mysql安装完后默认只有命令行工具,所以我们可以下载一些数据库管理工具Navicat Navicat使用 首先建立一个连接选择mysql,填写信息 发现多了一个localhost,双击,打开连 ...

  7. scala新版本学习(3)

    1.REPL:读取->求值->打印->循环.Scala程序将输入的内容快速的编译成为字节码,然后字节码文件交给Java虚拟机进行执行. 2.val是值不可变,var值可变.在变量声明 ...

  8. 13 Python之第一类对象闭包和迭代器

      def fn():     print("我叫fn") fn() print(fn)## <function fn at 0x0000000001D12E18> f ...

  9. 原生javascript的意义

    原生JS是指遵循ECMAscript标准的javascript,不同于微软的jscript也不依赖于任何框架,依托于浏览器标准引擎的脚本语言. jquery是在原生态的js上集成的框架资源,使用jqu ...

  10. VUE实现国际化

    一.前言 趁着11月的最后一天,来写一篇关于前端国际化的实践型博客.国际化应该都不陌生,就是一个网站.应用可以实现语言的切换. 在这就不谈原理,只说说如何实现中英文的切换.做技术的总得先把 demo ...