整体二分

ooliver 发布于 2026-03-22 375 次阅读 OI


AI 摘要

⚡你有没有好奇过:一个算法模板,凭什么能一口气解决【区间第k小】【矩阵第k小】【流星雨】甚至【射木板】四种完全不同的问题?我告诉你——这是整体二分,一个能把“二分答案”玩成通杀绝技的思维武器。

P3834 【模板】可持久化线段树 2

模板,直接看代码:

C++
#include<bits/stdc++.h>
using namespace std;

#define lowbit(x) x&-x
const int N=2e5+5;

int n,m,cnt;
int ans[N],tree[N];
int maxn=INT_MIN,minn=INT_MAX;

struct node{
    int x,y,k,id,op;
}q[N<<1],q1[N<<1],q2[N<<1];

struct BIT{
    int p[N];
    void add(int x,int k){
        for(int i=x;i<=n;i+=lowbit(i)) p[i]+=k;
    }
    int sum(int x){
        int res=0;
        for(int i=x;i>=1;i-=lowbit(i)) res+=p[i];
        return res;
    }
}bit;

void solve(int l,int r,int vl,int vr){
    if(l>r) return;
    if(vl==vr){
        for(int i=l;i<=r;i++)
            if(q[i].op) ans[q[i].id]=vl;
        return;
    }
    int mid=vl+vr>>1;
    int cnt1=0,cnt2=0;
    for(int i=l;i<=r;i++){
        if(!q[i].op){
            if(q[i].x<=mid){
                bit.add(q[i].id,1);
                q1[++cnt1]=q[i];
            }
            else q2[++cnt2]=q[i];
        }
        else{
            int s=bit.sum(q[i].y)-bit.sum(q[i].x-1);
            if(s>=q[i].k) q1[++cnt1]=q[i];
            else{
                q[i].k-=s;
                q2[++cnt2]=q[i];
            }
        }
    }
    for(int i=1;i<=cnt1;i++) if(!q1[i].op) bit.add(q1[i].id,-1);
    for(int i=1;i<=cnt1;i++) q[i+l-1]=q1[i];
    for(int i=1;i<=cnt2;i++) q[i+l+cnt1-1]=q2[i];
    solve(l,l+cnt1-1,vl,mid);
    solve(l+cnt1,r,mid+1,vr);
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        q[++cnt]={x,0,0,i,0};
        minn=min(minn,x),maxn=max(maxn,x);
    }
    for(int i=1;i<=m;i++){
        int x,y,k;
        cin>>x>>y>>k;
        q[++cnt]={x,y,k,i,1};
    }
    solve(1,cnt,minn,maxn);
    for(int i=1;i<=m;i++) cout<<ans[i]<<"\n";
    return 0;
}

P1527 [国家集训队] 矩阵乘法

上一题的二维版本,把树状数组改成二维的即可,代码:

P3527 [POI 2011] MET-Meteors

每次询问的答案具有单调性,考虑整体二分。

相对于模板,把树状数组的操作改为区间修改、单点查询,注意在计算时要把每个国家所占所有轨道都计算上。

代码:

P3332 [ZJOI2013] K 大数查询

相较于板子发现需要一个支持区间修改和区间查询的数据结构,考虑线段树,其它都差不多了。

P7424 [THUPC 2017] 天天爱射击

答案明显具有单调性,考虑整体二分。

其余二分答案没啥好说的,一个答案区间,一个处理询问区间,先假设答案区间前一半的子弹都发射,再把询问区间的木板分成两部分,这些都是整体二分的套路。

代码: