整体二分模板

静态区间第\(k\)

总结:码量小,感觉比较好写,常数优秀,大约是主席树的1.5倍速度左右。

Code:

#include <cstdio>
#include <algorithm>
const int N=2e5+10;
struct node{int l,r,k,id;}qry[N<<1],ql[N<<1],qr[N<<1];
int n,m,ans[N],b[N],s[N];
void add(int x,int d){while(x<=n)s[x]+=d,x+=x&-x;}
int query(int x){int sum=0;while(x)sum+=s[x],x-=x&-x;return sum;}
void divide(int l,int r,int s,int t)
{
    if(s>t) return;
    if(l==r)
    {
        for(int i=s;i<=t;i++) ans[qry[i].id]=b[l];
        return;
    }
    int mid=l+r>>1,lp=0,rp=0;
    for(int i=s;i<=t;i++)
        if(!qry[i].id)
        {
            if(qry[i].k<=mid) add(qry[i].l,1),ql[++lp]=qry[i];
            else qr[++rp]=qry[i];
        }
    for(int i=s;i<=t;i++)
        if(qry[i].id)
        {
            int c=query(qry[i].r)-query(qry[i].l-1);
            if(c>=qry[i].k) ql[++lp]=qry[i];
            else qr[++rp]=qry[i],qr[rp].k-=c;
        }
    for(int i=s;i<=t;i++)
        if(!qry[i].id&&qry[i].k<=mid)
            add(qry[i].l,-1);
    for(int i=s;i<=s+lp-1;i++) qry[i]=ql[i+1-s];
    for(int i=s+lp;i<=t;i++) qry[i]=qr[i+1-s-lp];
    divide(l,mid,s,s+lp-1),divide(mid+1,r,s+lp,t);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&qry[i].k),b[i]=qry[i].k,qry[i].l=i;
    std::sort(b+1,b+1+n);
    int cnt=std::unique(b+1,b+1+n)-b-1;
    for(int i=1;i<=n;i++) qry[i].k=std::lower_bound(b+1,b+1+cnt,qry[i].k)-b;
    for(int i=1;i<=m;i++) scanf("%d%d%d",&qry[i+n].l,&qry[i+n].r,&qry[i+n].k),qry[i+n].id=i;
    divide(1,cnt,1,n+m);
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}


2018.10.31

posted @ 2018-10-31 19:32  露迭月  阅读(208)  评论(0编辑  收藏  举报