【学习笔记】整体二分
一. 整体二分概念
整体二分的主体思路就是把多个查询一起解决,是一个离线算法。
其要求:
-
询问的答案具有可二分性
-
修改对判定答案的贡献互相独立,修改之间互不影响效果
-
修改如果对判定答案有贡献,则贡献为一确定的与判定标准无关的值
-
贡献满足交换律,结合律,具有可加性
-
题目允许使用离线算法
其大体结构框架:
设 为答案的值域, 为答案的定义域。
那么二分答案时考虑下标在 中的操作和询问,答案在值域 中。
二. 静态区间第 小
由一道题引入整体二分的具体实现。
给定 个整数构成的序列 ,将对于指定的闭区间 查询其区间内的第 小值。
,,,。
静态区间第 小,一个经典的问题。
显然可以用主席树做,这里我们考虑用整体二分。
与 cdq 分治类似,将询问和修改都看成“操作”。我们首先把所有操作按时间顺序存入数组中,然后开始分治,定义函数
solve(l,r,s,t)
表示在值域 上二分处理 这些操作
在每一层分治中,考虑利用数据结构(常用树状数组)统计当前查询的答案和 之间的关系。
根据查询出来的答案和 间的关系( 或者 )将当前处理的操作序列分为两份,并分别递归处理(注意修改和询问都要递归)。
边界:当 时,找到答案,记录答案并返回即可。
需要注意的是,在整体二分过程中,solve(l,r,s,t)
只处理答案在 内的询问,最终答案范围不在 的询问会在其他 solve
函数中处理。
比如,我们现在有这样一个 的序列:
查询次数为
考虑用整体二分的思想。
原序列的值域显然为 。
这里注意最好先将原序列离散化后求值域。
那么 。
考虑将这个序列分成两类:
一类是权值 ,另一类是 的。
我们把这两类用下标表示出来:
注意这里指下标,而不是权值。
考虑第一个询问 。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+6;
const int inf=1e9;
int n,m,tr[N],ans[N];
struct node{
int x,y,k,id;
bool flag;
}a[N],b[N],c[N];
inline int lowbit(int x){
return x&(-x);
}
inline void update(int x,int val){
while(x<=n){
tr[x]+=val;
x+=lowbit(x);
}
return;
}
inline int query(int x){
int res=0;
while(x){
res+=tr[x];
x-=lowbit(x);
}
return res;
}
inline void solve(int l,int r,int s,int t){
if(s>t)return;
if(l==r){
for(int i=s;i<=t;i++)if(a[i].flag)ans[a[i].id]=l;
return;
}
int mid=(l+r)>>1,p=0,q=0;
for(int i=s;i<=t;i++){
if(!a[i].flag){
if(a[i].x<=mid){
update(a[i].id,1);
b[++p]=a[i];
}
else c[++q]=a[i];
}
else{
int res=query(a[i].y)-query(a[i].x-1);
if(res>=a[i].k)b[++p]=a[i];
else{
a[i].k-=res;
c[++q]=a[i];
}
}
}
for(int i=1;i<=p;i++)if(!b[i].flag)update(b[i].id,-1);
for(int i=1;i<=p;i++)a[i+s-1]=b[i];
for(int i=1;i<=q;i++)a[i+s+p-1]=c[i];
solve(l,mid,s,s+p-1);
solve(mid+1,r,s+p,t);
return;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
a[i].x=x;
a[i].y=1;
a[i].k=inf;
a[i].id=i;
a[i].flag=false;
}
for(int i=1;i<=m;i++){
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
a[i+n].x=x;
a[i+n].y=y;
a[i+n].k=k;
a[i+n].id=i;
a[i+n].flag=true;
}
solve(-inf,inf,1,n+m);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}
本文作者:trsins
本文链接:https://www.cnblogs.com/trsins/p/17970741
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2022-01-17 【做题记录】Ynoi2018 天降之物
2022-01-17 【学术】连分数
2022-01-17 【做题记录】Ynoi2015 盼君勿忘
2022-01-17 【做题记录】BJOI2016 水晶
2022-01-17 【做题记录】P4965 薇尔莉特的打字机
2022-01-17 【做题记录】POI2011 Lightning Conductor
2022-01-17 【做题记录】CF961G Partitions