hdu6278(二分主席树,求区间中最大的x,满足大于等于x的数量大于等于x)

题:http://acm.hdu.edu.cn/showproblem.php?pid=6278

题意:求区间中最大的x,满足大于等于x的数量大于等于x

分析:二分找答案,check(mid)为查询区间中第len-mid+1大的数是否大于mid

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int mod=10007;
const int M=2e5+5;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
int a[M],b[M];
struct ChairTree{
    int root[M],cnt;
    struct node{
        int sum,L,R;
    }tr[M*40];
    void Clear(int n){
        for(int i=0;i<=n;i++)
            tr[i].sum=tr[i].L=tr[i].R=0;
    }
    void update(int &rt,int pos,int l,int r){
        tr[++cnt]=tr[rt];
        tr[cnt].sum++;
        rt=cnt;
        if(l==r)
            return;
        int midd=(l+r)>>1;
        if(pos<=midd)
            update(tr[rt].L,pos,l,midd);
        else
            update(tr[rt].R,pos,midd+1,r);
    }
    int query(int i,int j,int k,int l,int r){
        int num=tr[tr[j].L].sum-tr[tr[i].L].sum;
        if(l==r)
            return l;
        int midd=(l+r)>>1;
        if(num>=k)
            return query(tr[i].L,tr[j].L,k,l,midd);
        else
            return query(tr[i].R,tr[j].R,k-num,midd+1,r);
    }
}t1;
int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+1+n);
        int p=unique(b+1,b+1+n)-b-1;
        t1.cnt=0;
        for(int i=1;i<=n;i++){
            t1.root[i]=t1.root[i-1];
            int pos=lower_bound(b+1,b+1+p,a[i])-b;
            t1.update(t1.root[i],pos,1,p);
        }
        while(m--){
            int x,y;
            scanf("%d%d",&x,&y);
            int len=y-x+1;
            int l=0,r=len,ans=0;
            while(l<=r){
                int midd=(l+r)>>1;
                if(b[t1.query(t1.root[x-1],t1.root[y],len-midd+1,1,p)]>=midd){
                    ans=max(ans,midd);
                    l=midd+1;
                }
                else
                    r=midd-1;
            }
            printf("%d\n",ans);
        }
        t1.Clear(t1.cnt);

    }
    return 0;
}
View Code

 

posted @ 2020-09-18 14:57  starve_to_death  阅读(204)  评论(0编辑  收藏  举报