[洛谷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\)之后就别管它了,把它用并查集连到它父亲上 它 ...
随机推荐
- 洛谷 P2534 [AHOI2012]铁盘整理
P2534 [AHOI2012]铁盘整理 题目描述 输入输出格式 输入格式: 共两行.第一行为铁盘个数N(1<=N<=50),第二行为N个不同的正整数,分别为从上到下的铁盘的半径R.(1& ...
- ASP内置对象—Request、Response 、Server、Application 、ObjectContent (二)
Response (应答)对象 Request 对象.用于在HTTP请求期间,訪问不论什么client浏览器传递给server的信息,包含通过URL传递的參数信息.使用GET方法或POST方法传递的H ...
- IOS - 查找未使用的图片
实现细节都在代码里面, 帮助 -h. # -*- coding: utf-8 -*- """ 检查IOS应用图片是否使用 1. 读取有效文件: 图片(.png, .jpg ...
- Google面试题-高楼扔鸡蛋问题
本文由 @lonelyrains 出品.转载请注明出处. 文章链接: http://blog.csdn.net/lonelyrains/article/details/46428569 高楼扔鸡蛋问 ...
- 使用imgareaselect 辅助后台进行图片裁剪
由于项目其中用到图片裁剪,本来能够不用到后台进行裁剪的,可是要兼容万恶的IE浏览器,所以不得不使用后台进行裁剪. 这次使用到imgareaselect 插件获取须要裁剪区域的坐标.再由后台进行裁剪操作 ...
- 安卓离线SDK Windows版 资源包下载地址全集
1.Tools https://dl-ssl.google.com/android/repository/platform-tools_r19.0.1-windows.zip https://d ...
- Truck History --hdoj
Truck History Time Limit : 4000/2000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other) Tota ...
- JS 中构造函数和普通函数的区别(详)
1.构造函数也是一个普通函数,创建方式和普通函数一样,但构造函数习惯上首字母大写 2.构造函数和普通函数的区别在于:调用方式不一样.作用也不一样(构造函数用来新建实例对象) 3.调用方式不一样. 普通 ...
- BZOJ 2659 数学
思路: 一开始以为是真·欧几里德 a,b来回消 (其实用不了那么麻烦) 我们发现 这是一个矩形 求一下整点数 完了.. 要特判 p=q的情况 //By SiriusRen #include <c ...
- 查看 myeclipse激活状态
查看激活状态 myeclipse-->subscription information