[POJ2104]Kth Number-[整体二分]

Description

传送门

Solution

将所有询问放在一起,二分答案的同时把区间[l,r]内的数按大小分类。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct P{int num,id;}b[100100];
bool cmp(P x,P y){return x.num<y.num;}
int rk[100100],all=0;

int n,m,a[100100];
struct node{int l,r,k,id;
}q[50010],st[2][50010];int ans[50010];

int suml[100010],sumr[100010],_sort[100010];
void solve(int ql,int qr,int l,int r,int ansl,int ansr)
{
    if (ql>qr) return;
    if (ansl==ansr) 
    {
        for (int i=ql;i<=qr;i++) ans[q[i].id]=ansl;
        return;
    }
    int ansmid=ansl+ansr>>1,cnt=0,js0=0,js1=0;
    suml[l-1]=sumr[l-1]=0;
    for (int i=l;i<=r;i++)
    {
        suml[i]=a[i]<=ansmid;sumr[i]=a[i]>ansmid;
        if (a[i]<=ansmid) _sort[++cnt]=a[i];
    }
    for (int i=l;i<=r;i++) if (a[i]>ansmid) _sort[++cnt]=a[i];
    for (int i=l;i<r;i++) suml[i+1]+=suml[i],sumr[i+1]+=sumr[i];
    for (int i=ql;i<=qr;i++)
    if (suml[q[i].r+l-1]-suml[q[i].l+l-2]>=q[i].k)
    {
        st[0][++js0]=q[i];
        st[0][js0].l=suml[q[i].l+l-1];
        st[0][js0].r=suml[q[i].r+l-1];
        if (a[q[i].l+l-1]>ansmid) ++st[0][js0].l;
    } else
    {
        st[1][++js1]=q[i];
        st[1][js1].l=sumr[q[i].l+l-1];
        st[1][js1].r=sumr[q[i].r+l-1];
        st[1][js1].k-=suml[q[i].r+l-1]-suml[q[i].l+l-2];
        if (a[q[i].l+l-1]<=ansmid) ++st[1][js1].l;
    }
    for (int i=1;i<=js0;i++) q[i+ql-1]=st[0][i];
    for (int i=1;i<=js1;i++) q[i+ql+js0-1]=st[1][i];
    for (int i=l;i<=r;i++) a[i]=_sort[i-l+1];
    solve(ql,ql+js0-1,l,l+suml[r]-1,ansl,ansmid);
    solve(ql+js0,qr,l+suml[r],r,ansmid+1,r);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) 
    {
        scanf("%d",&b[i].num);b[i].id=i;
    }
    sort(b+1,b+n+1,cmp);
    for (int i=1;i<=n;i++)
    {
        if (b[i].num!=b[i-1].num) all++,rk[all]=b[i].num;
        a[b[i].id]=all;
    }
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);q[i].id=i;
    }
    solve(1,m,1,n,1,n);
    for (int i=1;i<=m;i++) printf("%d\n",rk[ans[i]]);
    
}

猜你喜欢

转载自www.cnblogs.com/coco-night/p/9495129.html