静态区间第k小 - 整体二分

Posted mollnn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了静态区间第k小 - 整体二分相关的知识,希望对你有一定的参考价值。

蒟蒻终于学会整体二分啦!

思路

技术图片

实现

技术图片

丑陋无比的代码

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

const int N = 200005;
int ar[N];
int lowbit(int t) { return t & (-t); }
void add(int i, int v) {
    for (; i < N; ar[i] += v, i += lowbit(i));
}
int sum(int i) {
    int s = 0;
    for (; i > 0; s += ar[i], i -= lowbit(i));
    return s;
}


struct Elem {
    int pos,val;
    bool operator < (const Elem &b) {
        return val < b.val;
    }
} e[200005];

struct Query {
    int l,r,k,ans;
} q[200005];

int n,m,a[200005];

void solve(int l,int r,vector<int> num,vector <int> v) {
    //cout<<l<<" "<<r<<" "<<num.size()<<" "<<v.size()<<endl;
    if(l==r) {
        for(int i=0;i<v.size();i++) {
            q[v[i]].ans = l;
        }
    }
    else {
        memset(ar,0,sizeof ar);
        vector <int> v1,v2,n1,n2;
        int mid = (l+r)>>1;
        for(int i=0;i<num.size();i++) {
            if(e[num[i]].val<=mid) {
                add(e[num[i]].pos,1);
                n1.push_back(num[i]);
            }
            else {
                n2.push_back(num[i]);
            }
        }
        for(int i=0;i<v.size();i++) {
            if(sum(q[v[i]].r)-sum(q[v[i]].l-1) >= q[v[i]].k) {
                v1.push_back(v[i]);
            }
            else {
                q[v[i]].k -= sum(q[v[i]].r)-sum(q[v[i]].l-1);
                v2.push_back(v[i]);
            }
        }
        if(v1.size()) solve(l,mid,n1,v1);
        if(v2.size()) solve(mid+1,r,n2,v2);
    }
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        e[i].pos=i;
        e[i].val=a[i];
    }
    sort(e+1,e+n+1);
    for(int i=1;i<=m;i++) {
        scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
    }
    vector <int> tmp;
    vector <int> num;
    for(int i=1;i<=n;i++) {
        num.push_back(i);
    }
    for(int i=1;i<=m;i++) {
        tmp.push_back(i);
    }
    solve(-1e+9,1e+9,num,tmp);
    for(int i=1;i<=m;i++) {
        cout<<q[i].ans<<endl;
    }
}

以上是关于静态区间第k小 - 整体二分的主要内容,如果未能解决你的问题,请参考以下文章

整体二分学习

整体二分

整体二分初探 两类区间第K大问题 poj2104 & hdu5412

BZOJ 3110:[Zjoi2013]K大数查询(整体二分)

数据结构之主席树

关于求解区间第k大的在线和离线做法