zoukankan      html  css  js  c++  java
  • cogs930

    找第k小的数

    输入文件:kth.in 输出文件:kth.out 简单对比
    时间限制:1 s 内存限制:256 MiB

    【题目描述】

    看到很短的题目会让人心情愉悦,所以给出一个长度为N的序列A1,A2,A3,...,AN,
    现在有M个询问,每个询问都是Ai...Aj中第k小的数等于多少。

    【输入格式】

    第一行两个正整数N,M。
    第二行N个数,表示序列A1,A2,...,AN。
    紧着的M行,每行三个正整数i,j,k(k≤j-i+1),表示
    询问Ai...Aj中第k小的数等于多少。

    【输出格式】

    共输出M行,第i行输出第i个询问的答案。

    【样例输入1】

    4 3
    4 1 2 3
    1 3 1
    2 4 3
    1 4 4 
    

    【样例输出1】

    1
    3
    4
    

    【样例输入2】

    5 5
    4 2 9 9 10
    1 3 1
    2 4 3
    1 4 4
    3 5 2
    2 5 2
    

    【样例输出2】

    2
    9
    9
    9
    9
    

    【提示】

    询问区间的第k小值并非严格第k小,例如样例2中第4个询问,询问3到5中第2小的数,
    答案输出9,并不是严格第2小的10。

    在50%的数据中,1<=N<=10,000,1<=M<=10,000,A[i]<=100,000;
    在100%的数据中,1<=N<=100,000,1<=M<=100,000,A[i]<=1,000,000;


    原本是要刷一个CDQ分支的题目,可是做不出来。后来看题解才知道是整体二分!也就学习了一下。
    整体二分,简单来说,就是把多个询问进行一起二分答案!
    比CDQ分治要难!


    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    const int maxm=1e6+10;
    int n,m;
    struct num
    {
        int p,x;
    }a[maxn],a1[maxn],a2[maxn];
    struct que
    {
        int l,r,k,id;
    }q[maxm],q1[maxm],q2[maxm];
    int sm[maxm];
    void add(int pos,int x)
    {
        for(int i=pos;i<=1000000;i+=i&-i)sm[i]+=x;
    }
    int query(int pos)
    {
        int ret=0;
        for(int i=pos;i;i-=i&-i)ret+=sm[i];
        return ret;
    }
    int ans[maxn];
    void solove(int l,int r,int al,int ar,int ql,int qr)
    {
        if(l>r||ql>qr||al>ar)return;
        if(l==r)
        {
            for(int i=ql;i<=qr;++i)ans[q[i].id]=l;
            return ;
        }
        int mid=(l+r)>>1;
        int a1c=0,a2c=0;
        for(int i=al;i<=ar;++i)
        {
            if(a[i].x<=mid)
            {
                add(a[i].p,1);a1[al+a1c]=a[i];a1c++;
            }
            else a2[al+a2c]=a[i],++a2c;
        }
        int q1c=0,q2c=0;
        for(int i=ql;i<=qr;++i)
        {
            int tp=query(q[i].r)-query(q[i].l-1);
            if(tp>=q[i].k)q1[ql+q1c]=q[i],++q1c;
            else q[i].k-=tp,q2[ql+q2c]=q[i],++q2c;
        }
        for(int i=al;i<al+a1c;++i)a[i]=a1[i];
        for(int i=al+a1c;i<=ar;++i)a[i]=a2[i-a1c];
        for(int i=ql;i<ql+q1c;++i)q[i]=q1[i];
        for(int i=ql+q1c;i<=qr;++i)q[i]=q2[i-q1c];
        for(int i=al;i<al+a1c;++i)add(a1[i].p,-1);
        solove(l,mid,al,al+a1c-1,ql,ql+q1c-1);
        solove(mid+1,r,al+a1c,ar,ql+q1c,qr);
    }
    int mx=-1,mn=1000001;
    int main()
    {
        freopen("kth.in","r",stdin);
        freopen("kth.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i].x),a[i].p=i;
            mx=max(mx,a[i].x);
            mn=min(mn,a[i].x);
        }
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
            q[i].id=i;
        }
        solove(mn,mx,1,n,1,m);
        for(int i=1;i<=m;++i)printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    ABAP 表格控制(Table Control)和步循环
    ABAP中正则表达式的简单使用方法 (转老白BLOG)
    ABAP常用函数集锦
    ALV用例大全
    DXP 笔记
    STM32笔记——Power Controller(PWR)
    STM32之glossary
    STM32 解析futaba S-bus协议
    Windows下 vundle的安装和使用
    使用串口绘制实时曲线 —— SerialChart
  • 原文地址:https://www.cnblogs.com/gryzy/p/15515395.html
Copyright © 2011-2022 走看看