链接:

P3332


题意:

维护 \(n(1\leq n\leq 5\times10^4)\) 个可重整数集,编号从 \(1\) 到 \(n\)。有 \(m(1\leq m\leq5\times10^4)\) 个操作:

  • 1 l r c 表示将 \(c\) 插入到编号在 \([l,r]\) 的集合中。
  • 2 l r c 表示查询编号在 \([l,r]\) 的集合的并集中的第 \(c\) 大数。

分析:

这道题除了用树套树等方法外,还可以用整体二分

参考《浅谈数据结构题的几个非经典解法》的介绍:

所谓整体二分,需要数据结构题满足以下性质:

  1. 询问的答案具有可二分性
  2. 修改对判定答案的贡献相对独立,修改之间互不影响效果
  3. 修改如果对判定答案有贡献,则贡献为一确定的与判定标准无关的值
  4. 贡献满足交换律,结合律,具有可加性
  5. 题目允许离线操作

    询问的答案有可二分性质显然是前提,我们发现,因为修改对判定标准的贡献相对独立,且贡献的值(如果有的话)与判定标准无关,所以如果我们已经计算过某一些修改对询问的贡献,那么这个贡献永远不会改变,我们没有必要当判定标准改变时再次计算这部分修改的贡献,只要记录下当前的总贡献,再进一步二分时,直接加上新的贡献即可。

    这样的话,我们发现,处理的复杂度可以不再与序列总长度直接相关了,而可能只与当前待处理序列的长度相关

简而言之:答案本身可以二分,修改之间互不影响,每个修改对每个查询的贡献不变,贡献可以直接加减,允许离线。

以及FSYo巨巨的图:

回到这道题上:

首先考虑普通二分:对每个查询考虑在它前面的所有修改,二分答案并将大于答案的修改在线段树上区间加一,再看查询的区间有多少大于答案的数,时间复杂度为 \(O(n\log n+m^2\log n)\)。将 \(n,m\) 视为同阶就是 \(O(n^2\log n)\)。这样对于每个查询分别二分会很慢,整体二分就可以把所有查询一次性解决。

具体操作是这样的,首先把所有修改和查询拉到一条序列上,维护这条当前序列在数组上的范围 \([l,r]\) 和答案范围 \([ansl,ansr]\),在本题中分别为 \(1,m,-n,n\)。然后要将这条序列分成两部分,但不是对半分,和普通二分类似的操作:首先令 \(mid=(ansl+ansr)/2\),从左往右扫,对每个扫到的修改,如果大于 \(mid\),那就在线段树上区间加一,并将这个修改放到左部分;如果小于等于 \(mid\),就把修改放到右部分。对每个扫到的询问,看查询区间有多少大于 \(mid\) 的数,如果数量小了,说明 \(mid\) 过大,所以把询问放到左边;如果数量大了,说明 \(mid\) 小了,我们减去查询到的数(意味着左边的贡献全部接受),然后把询问放到右边。然后左右两部分分治下去,每次把线段树清空。

感性理解一下,放到左边的查询是答案大了要减小,放到右边的查询是答案小了要增大,所以右边的查询不仅要减去左边的修改的贡献,还要在右边选择其他修改的贡献,而左边的查询则需要在左边的贡献中再选择。

整体二分把所有询问一次性同时解决了,时间复杂度降为了 \(O(n\log n^2)\),非常的强大。


代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
inline int read(){
int p=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}
return p*f;
}
const int N=1e5+5;
int n,m;
struct ques{
int opt,l,r,c,o;
}q[N],tl[N],tr[N];
int sum[N<<2],tag[N<<2],cov[N<<2];
inline void pushup(int p){sum[p]=sum[p<<1]+sum[p<<1|1];}
inline void f(int l,int r,int p,int d){
sum[p]+=(r-l+1)*d;
tag[p]+=d;
}
inline void cf(int p){sum[p]=tag[p]=0;cov[p]=1;}
inline void pushdown(int l,int r,int p){
if(cov[p]){
cf(p<<1);
cf(p<<1|1);
cov[p]=0;
}
if(tag[p]){
int mid=(l+r)>>1;
f(l,mid,p<<1,tag[p]);
f(mid+1,r,p<<1|1,tag[p]);
tag[p]=0;
}
}
inline void change(int l,int r,int p,int cl,int cr,int d){
if(l>=cl&&r<=cr){f(l,r,p,d);return ;}
pushdown(l,r,p);
int mid=(l+r)>>1;
if(cl<=mid)change(l,mid,p<<1,cl,cr,d);
if(cr>mid)change(mid+1,r,p<<1|1,cl,cr,d);
pushup(p);
}
inline int query(int l,int r,int p,int ql,int qr){
if(l>=ql&&r<=qr)return sum[p];
pushdown(l,r,p);
int mid=(l+r)>>1,res=0;
if(ql<=mid)res+=query(l,mid,p<<1,ql,qr);
if(qr>mid)res+=query(mid+1,r,p<<1|1,ql,qr);
return res;
}
int vis[N];
int ans[N];
inline void solve(int l,int r,int ansl,int ansr){
if(l>r)return ;
if(ansl==ansr){
for(int i=l;i<=r;i++)
if(q[i].opt==2)ans[q[i].o]=ansl;
return ;
}
bool bl=false,br=false;cf(1);
int ll=0,rr=0,mid=(ansl+ansr)>>1;
for(int i=l;i<=r;i++){
if(q[i].opt==1){
if(q[i].c>mid){
change(1,n,1,q[i].l,q[i].r,1);
tr[++rr]=q[i];
}
else tl[++ll]=q[i];
}
else{
int t=query(1,n,1,q[i].l,q[i].r);
if(t>=q[i].c)
tr[++rr]=q[i],br=true;
else{
q[i].c-=t;
tl[++ll]=q[i],bl=true;
}
}
}
for(int i=1;i<=ll;i++)q[l+i-1]=tl[i];
for(int i=ll+1;i<=ll+rr;i++)q[l+i-1]=tr[i-ll];
if(bl)solve(l,l+ll-1,ansl,mid);
if(br)solve(l+ll,r,mid+1,ansr);
}
int qn;
signed main(){
n=in,m=in;
for(int i=1;i<=m;i++)
q[i].opt=in,q[i].l=in,q[i].r=in,q[i].c=in,q[i].o=(q[i].opt==2)?++qn:0;
solve(1,m,-n,n);
for(int i=1;i<=qn;i++)
cout<<ans[i]<<'\n';
return 0;
}

例题推荐:

P2617 Dynamic Rankings

洛谷 P3332 [ZJOI2013]K大数查询 (整体二分理解)的更多相关文章

  1. 洛谷 P3332 [ZJOI2013]K大数查询 解题报告

    P3332 [ZJOI2013]K大数查询 题目描述 有\(N\)个位置,\(M\)个操作.操作有两种,每次操作如果是\(\tt{1\ a\ b\ c}\)的形式表示在第\(a\)个位置到第\(b\) ...

  2. 洛谷 P3332 [ZJOI2013]K大数查询 || bzoj3110

    用树套树就很麻烦,用整体二分就成了裸题.... 错误: 1.尝试线段树套平衡树,码农,而且n*log^3(n)慢慢卡反正我觉得卡不过去 2.线段树pushdown写错...加法tag对于区间和的更新应 ...

  3. P3332 [ZJOI2013]K大数查询 整体二分

    终于入门整体二分了,勉勉强强算是搞懂了一个题目吧. 整体二分很多时候可以比较好的离线处理区间\(K\)大值的相关问题.考虑算法流程: 操作队列\(arr\),其中有询问和修改两类操作. 每次在答案的可 ...

  4. [洛谷P3332][ZJOI2013]K大数查询

    题目大意:有$n$个位置,$m$个操作.操作有两种: $1\;l\;r\;x:$在区间$[l,r]$每个位置加上一个数$x$ $2\;l\;r\;k:$询问$[l,r]$中第$k$大的数是多少. 题解 ...

  5. 洛谷P3332 [ZJOI2013]K大数查询 权值线段树套区间线段树_标记永久化

    Code: #include <cstdio> #include <algorithm> #include <string> #include <cstrin ...

  6. BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)

    题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...

  7. BZOJ 3110: [Zjoi2013]K大数查询 [整体二分]

    有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. N ...

  8. BZOJ3110:[ZJOI2013]K大数查询(整体二分)

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位 ...

  9. [ZJOI2013]K大数查询——整体二分

    题目描述 有N个位置,M个操作.操作有两种,每次操作如果是: 1 a b c:表示在第a个位置到第b个位置,每个位置加上一个数c 2 a b c:表示询问从第a个位置到第b个位置,第C大的数是多少. ...

随机推荐

  1. JAVA安全基础之代理模式(二)

    JAVA安全基础之代理模式(二) 上篇讲到静态代理模式,这时候我们发现,一个代理类只能为一个类服务,如果需要代理的类很多,那么就需要编写大量的代理类,比较繁琐.所以就有了动态代理 动态代理 动态代理的 ...

  2. weblogic从ssrf到redis获取shell

    一.环境搭建和知识储备 1.1.影响版本 漏洞编号:CVE-2014-4210 weblogic 10.0.2.0 weblogic 10.3.6.0 1.2.Docker搭建环境 1.进入vulhu ...

  3. io流-文件流\节点流

    FileOutputStream类(jdk1.0) 描述 java.io.FileOutputStream 类是文件字节输出流,用于将数据写入到文件中. 构造方法 //构造方法 FileOutputS ...

  4. 【JDK】分析 String str=““ 与 new String()

    一.基础概念 为了讲清楚他们的差异,这里先介绍几个概念. 1.1 常量池 所谓常量池:顾名思义就是用来存放一些常量的.该常量是在编译期被确定,并被保存在已编译的.class文件中,其中包括了类,方法, ...

  5. Nginx:进程调度

    Blog:博客园 个人 Nginx采用的是固定数量的多进程模型,由一个主进程(MasterProcess)和数量与主机CPU核数相同的工作进程协同处理各种事件. 主管理进程负责工作进程的配置加载.启停 ...

  6. Marvell 88SE9215 AHCI驱动笔记

    禁止转载!禁止转载!禁止转载! 一.Marvell 88SE9215.AHCI与SATA简介 1.Marvell 88SE9215 1)概述 88SE9215是一个四端口,兼容3 Gbps和6 Gbp ...

  7. Android——ProgressBar(进度条)

    参考资料来源于菜鸟教程--学的不仅是技术,更是梦想! 学习! 1.常用属性讲解与基础实例 从官方文档,我们看到了这样一个类关系图: ProgressBar继承与View类,直接子类有AbsSeekBa ...

  8. rabbitmqctl 命令行管理工具

    1. 用户管理 用户管理包括增加用户,删除用户,查看用户列表,修改用户密码. (1) 新增一个用户 rabbitmqctl add_user Username Password (2) 删除一个用户 ...

  9. springweb项目自定义拦截器修改请求报文头

    面向切面,法力无边,任何脏活累活,都可以从干干净净整齐划一的业务代码中抽出来,无非就是加一层,项目里两个步骤间可以被分层的设计渗透成筛子. 举个例子: 最近我们对接某银行接口,我们的web服务都是标准 ...

  10. (目录)Fortran学习笔记:开坑!!!

    前言:因为某些原因,需要使用Fortran编写程序,记录下Fortran语法学习过程中的部分笔记.在此开坑记录,立下Flag,"希望年末能够更新完" Fortran 学习笔记 陈橙 ...