[洛谷P4887]第十四分块(前体)
题目大意:
给定一个长度为\(n\)的序列\(a\),\(k\),和\(m\)次询问。
每次询问给定区间\([l,r]\),求满足\(l\leqslant i< j\leqslant r\)且\(\_\_ \text{builtin}\_ \text{popcount} (a_i\oplus a_j)=k\)的数对\((i,j)\)的个数。
40MB。
解题思路:
二次离线莫队lxl黑科技。
对于一次询问\([l,r]\),我们考虑右端点往右移动一格后变成\([l,r+1]\),多出来的数其实是\(a_{r+1}\)在\([l,r]\)内的贡献。
而这个贡献相当于\(a_{r+1}\)在\([1,r]\)内的贡献减去\(a_{r+1}\)在\([1,l-1]\)内的贡献。
而\(a_{i+1}\)在区间\([1,i]\)内的贡献可以前缀和预处理出来,这部分贡献可以\(O(1)\)计算。
而当右指针移动的时候,左指针不会动,所以\([1,l-1]\)这个区间是不会变的。
设指针\(r\)往右移动到\(r'\),则把\([r+1,r']\)塞进\(v_{l-1}\)里去,表示\([1,l-1]\)这段区间对\([r+1,r']\)有贡献。往左移动同理,记录一下贡献的正负即可。
左指针移动的话,则反着再记录一个即可。注意右指针移动的时候,左指针没有动过,而左指针移动的时候,右指针已经移动完了。
而莫队保证每个指针移动的总距离是\(O(n\sqrt n)\)的,也就是说一个vector里存的区间总长是\(O(n\sqrt n)\)的,那么拿出来暴力计算即可。
要用一个桶记录当前状态,可以做到\(O(\binom{14}{k})\)插入(插入一个数,把这个数异或所有合法数的桶都+1),\(O(1)\)查询。
注意最后得到的结果是与上一次的贡献差,最后要做一个前缀和。
时间复杂度\(O(n\binom{14}{k}+n\sqrt n)\),常数巨大。空间复杂度\(O(n+m)\)。
C++ Code:
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
#include<cstring>
#define lim 16384
#define N 100005
#define reg register
class istream{
char buf[15000003],*s;
public:
inline istream(){
buf[fread(s=buf,1,15000001,stdin)]='\n';
}
template<typename T>
inline istream&operator>>(T&rhs){
for(rhs=0;!isdigit(*s);++s);
while(isdigit(*s))rhs=rhs*10+(*s++&15);
return*this;
}
}cin;
struct ostream{
char buf[8000005],*s;
inline ostream(){s=buf;}
inline void operator<<(long long d){
if(!d){
*s++='0';
}else{
static long long w;
for(w=1;w<=d;w*=10);
for(;w/=10;d%=w)*s++=d/w^'0';
}
*s++='\n';
}
inline ostream&operator<<(const char&c){*s++=c;return*this;}
inline~ostream(){fwrite(buf,1,s-buf,stdout);}
}cout;
int n,m,k,buc[lim+1],a[N],K[4000],KS;
long long ans[N],out[N],L_R[N],R_L[N];
struct que{
int l,r,id;
inline bool operator<(const que&rhs)const{
return((l/333!=rhs.l/333)?(l<rhs.l):(r<rhs.r));
}
}q[N];
struct node{
int l,r,id,op;
};
std::vector<node>L[N],R[N];
int main(){
cin>>n>>m>>k;
if(k>14){for(int i=1;i<=m;++i)puts("0");return 0;}
for(int i=0;i<lim;++i)
if(__builtin_popcount(i)==k)K[KS++]=i;
for(int i=1;i<=n;++i){
cin>>a[i];
L_R[i]=buc[a[i]]+L_R[i-1];
reg int j=0;
for(;j+8<KS;j+=8)
++buc[a[i]^K[j]],++buc[a[i]^K[j+1]],++buc[a[i]^K[j+2]],++buc[a[i]^K[j+3]],
++buc[a[i]^K[j+4]],++buc[a[i]^K[j+5]],++buc[a[i]^K[j+6]],++buc[a[i]^K[j+7]];
for(;j<KS;++j)++buc[a[i]^K[j]];
}
memset(buc,0,sizeof buc);
for(int i=n;i;--i){
R_L[i]=buc[a[i]]+R_L[i+1];
reg int j=0;
for(;j+8<KS;j+=8)
++buc[a[i]^K[j]],++buc[a[i]^K[j+1]],++buc[a[i]^K[j+2]],++buc[a[i]^K[j+3]],
++buc[a[i]^K[j+4]],++buc[a[i]^K[j+5]],++buc[a[i]^K[j+6]],++buc[a[i]^K[j+7]];
for(;j<KS;++j)++buc[a[i]^K[j]];
}
for(int i=1;i<=m;++i)cin>>q[i].l>>q[q[i].id=i].r;
std::sort(q+1,q+m+1);
q[0].l=1,q[0].r=0;
for(int i=1;i<=m;++i){
const que&now=q[i],pre=q[i-1];
ans[i]+=L_R[now.r]-L_R[pre.r]+R_L[now.l]-R_L[pre.l];
if(now.r>pre.r)
R[pre.l-1].push_back((node){pre.r+1,now.r,i,-1});else
if(now.r<pre.r)
R[pre.l-1].push_back((node){now.r+1,pre.r,i,1});
if(now.l<pre.l)
L[now.r+1].push_back((node){now.l,pre.l-1,i,-1});else
if(now.l>pre.l)
L[now.r+1].push_back((node){pre.l,now.l-1,i,1});
}
memset(buc,0,sizeof buc);
for(int i=1;i<=n;++i){
reg int j=0;
for(;j+8<KS;j+=8)
++buc[a[i]^K[j]],++buc[a[i]^K[j+1]],++buc[a[i]^K[j+2]],++buc[a[i]^K[j+3]],
++buc[a[i]^K[j+4]],++buc[a[i]^K[j+5]],++buc[a[i]^K[j+6]],++buc[a[i]^K[j+7]];
for(;j<KS;++j)++buc[a[i]^K[j]];
for(node j:R[i]){
const int l=j.l,r=j.r;
reg long long t=0,k=l;
for(;k+8<=r;k+=8)
t+=buc[a[k]],t+=buc[a[k+1]],t+=buc[a[k+2]],t+=buc[a[k+3]],
t+=buc[a[k+4]],t+=buc[a[k+5]],t+=buc[a[k+6]],t+=buc[a[k+7]];
for(;k<=r;++k)t+=buc[a[k]];
ans[j.id]+=t*j.op;
}
}
memset(buc,0,sizeof buc);
for(int i=n;i;--i){
reg int j=0;
for(;j+8<KS;j+=8)
++buc[a[i]^K[j]],++buc[a[i]^K[j+1]],++buc[a[i]^K[j+2]],++buc[a[i]^K[j+3]],
++buc[a[i]^K[j+4]],++buc[a[i]^K[j+5]],++buc[a[i]^K[j+6]],++buc[a[i]^K[j+7]];
for(;j<KS;++j)++buc[a[i]^K[j]];
for(node j:L[i]){
const int l=j.l,r=j.r;
reg long long t=0,k=l;
for(;k+8<=r;k+=8)
t+=buc[a[k]],t+=buc[a[k+1]],t+=buc[a[k+2]],t+=buc[a[k+3]],
t+=buc[a[k+4]],t+=buc[a[k+5]],t+=buc[a[k+6]],t+=buc[a[k+7]];
for(;k<=r;++k)t+=buc[a[k]];
ans[j.id]+=t*j.op;
}
}
for(int i=1;i<=m;++i)ans[i]+=ans[i-1],out[q[i].id]=ans[i];
for(int i=1;i<=m;++i)cout<<out[i];
return 0;
}
[洛谷P4887]第十四分块(前体)的更多相关文章
- 洛谷P4887 第十四分块(前体)(二次离线莫队)
题面 传送门 题解 lxl大毒瘤 我们考虑莫队,在移动端点的时候相当于我们需要快速计算一个区间内和当前数字异或和中\(1\)的个数为\(k\)的数有几个,而这个显然是可以差分的,也就是\([l,r]\ ...
- P4887 第十四分块(前体) 莫队
题意: 给你一个序列,每次询问l,r问多少个a[i]^a[j]有k个1,k固定. 序列长度1e5,a[i]<=2^14 时限1s,空间40M 题解: 个人其实开始没什么思路,看了题解也好久,题解 ...
- 洛谷 P4887 -【模板】莫队二次离线(第十四分块(前体))(莫队二次离线)
题面传送门 莫队二次离线 mol ban tea,大概是这道题让我第一次听说有这东西? 首先看到这类数数对的问题可以考虑莫队,记 \(S\) 为二进制下有 \(k\) 个 \(1\) 的数集,我们实时 ...
- Luogu4887 第十四分块(前体)
sto \(lxl\) orz 考虑莫队,每次移动端点,我们都要询问区间内和当前数字异或有 \(k\) 个 \(1\) 的数字个数 询问 \([l,r]\) 可以再次离线,拆成询问 \([1,l-1] ...
- 【LuoguP4887】第十四分块(前体)
题目链接 题意 区间两数异或在二进制下有 \(k\) 个 \(1\) 的对数. Sol 普通莫队的话,如果要实时维护好区间内的答案需要支持区间对一个数求答案. 直接做不是很好做,容易发现其实这也就是一 ...
- 莫队 [洛谷2709] 小B的询问[洛谷1903]【模板】分块/带修改莫队(数颜色)
莫队--------一个优雅的暴力 莫队是一个可以在O(n√n)内求出绝大部分无修改的离线的区间问题的答案(只要问题满足转移是O(1)的)即你已知区间[l,r]的解,能在O(1)的时间内求出[l-1, ...
- 洛谷P3935 Calculating(整除分块)
题目链接:洛谷 题目大意:定义 $f(x)=\prod^n_{i=1}(k_i+1)$,其中 $x$ 分解质因数结果为 $x=\prod^n_{i=1}{p_i}^{k_i}$.求 $\sum^r_{ ...
- 洛谷P3396 哈希冲突 (分块)
洛谷P3396 哈希冲突 题目背景 此题约为NOIP提高组Day2T2难度. 题目描述 众所周知,模数的hash会产生冲突.例如,如果模的数p=7,那么4和11便冲突了. B君对hash冲突很感兴趣. ...
- 洛谷P4004 Hello world!(分块+并查集)
传送门 虽然洛谷数据水,然而咱最终还是没有卡过uoj上的毒瘤数据-- 神tm全uoj就3个人过了这题-- 首先,每个数最多被开根\(6\)次,开到\(1\)之后就别管它了,把它用并查集连到它父亲上 它 ...
随机推荐
- [bzoj5118]Fib数列2_费马小定理_矩阵乘法
Fib数列2 bzoj-5118 题目大意:求Fib($2^n$). 注释:$1\le n\le 10^{15}$. 想法:开始一看觉得一定是道神题,多好的题面啊?结果...妈的,模数是质数,费马小定 ...
- Android执行时ART载入OAT文件的过程分析
在前面一文中,我们介绍了Android执行时ART,它的核心是OAT文件.OAT文件是一种Android私有ELF文件格式,它不仅包括有从DEX文件翻译而来的本地机器指令.还包括有原来的DEX文件内容 ...
- 使用Lucene对预处理后的文档进行创建索引(可执行)
时间: 2015/3/18 杨鑫newlife 对于文档的预处理后.就要開始使用Lucene来处理相关的内容了. 这里使用的Lucene的过程例如以下: 首先要为处理对象机那里索引 二是构建查询对象 ...
- Maven—Windows操作系统中安装配置Maven环境
今天难得的周末,借此难的机会总结一下关于maven的一些操作: 1.在安装maven之前要确认计算机已经安装并配置了JDK. 2.下载maven: maven-3.0.3:http://downloa ...
- xcode打包测试
模拟器的内存cpu网络,都是电脑的.xcode可以查看. Xcode7之前是限制人,限制电脑,限制app,限制真机调试的. Xcode7之后,做真机测试只需要apple id即可,会自动生成证书. X ...
- c17---指针
// // main.c // 指针基本概念 #include <stdio.h> // 基本数据类型作为函数的参数是值传递, 在函数中修改形参的值不会影响到外面实参的值 void cha ...
- TCP心跳包
所谓的心跳包就是客户端定时放送简单的信息给服务器端,告诉它我还在而已.代码就是每 隔几分钟发送一个固定信息给服务器端,服务器端回复一个固定信息.如果服务器端几分钟后没有收到客户端信息则视客户端断开.比 ...
- HIT Software Construction Lab6引发出来对锁的问题的探究
前言 做完lab5开始做lab6了鸭,哈工大计算机学院的学生永不停歇.在做lab6的时候,我在想移动猴子是锁一整个ladder(ADT)还是只锁一个ladder的一个域Monkey数组呢?这两个好像差 ...
- uirecorder录制脚本
安装步骤不再描述. 将手机通过数据线连接到mac 然后输入启动macaca的命令: macaca server --port 4444 --verbose & 在输入 命令:uirecorde ...
- VCRuntime静默安装
批处理脚本: "%~dp0\VC_X64Runtime\VC_x64Runtime.exe" /q"%~dp0\VC_X86Runtime\VC_X86Runtime.e ...