• [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
    ",rk[ans[i]]);
        
    }
  • 相关阅读:
    windows 命令修改IP
    iptables_forward
    python之pickle模块
    python之os.path模块
    python之random模块
    python基础之常用模块
    python基础之测试题
    python 集合(set)基础
    python编码与解码
    python3 字符串基础
  • 原文地址:https://www.cnblogs.com/coco-night/p/9495129.html
Copyright © 2020-2023  润新知