• POJ 2104 求序列里第K大 主席树裸题


    给定一个n的序列,有m个询问 每次询问求l-r 里面第k大的数字是什么

    只有询问,没有修改

    可以用归并树和划分树(我都没学过。。囧)

    我是专门冲着弄主席树来的

    对主席树的建树方式有点了解了,不过这题为什么是在主席树里面这么操作的 还是有点不懂,今天照着模板敲了一遍就打多校了

    再研究吧

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=110010;
    const int maxm=maxn*30;
    int n,m,tot,s;
    int A[maxn],t[maxn],T[maxn];
    int c[maxm],lson[maxm],rson[maxm];
    int build(int l,int r)
    {
        int rt=++tot;
        c[rt]=0;
        if (l>=r) return rt;
        int mid=(l+r)>>1;
        lson[rt]=build(l,mid);
        rson[rt]=build(mid+1,r);
        return rt;
    }
    int update(int rt,int pos,int val)
    {
       int newrt=++tot,tmp=newrt;
       c[newrt]=c[rt]+val;
       int l=1,r=s;
       while (l<r)
       {
           int mid=(l+r)>>1;
           if (pos<=mid){
               r=mid;
               lson[newrt]=++tot;rson[newrt]=rson[rt];
               newrt=lson[newrt];rt=lson[rt];
           }
           else{
               l=mid+1;
               rson[newrt]=++tot;lson[newrt]=lson[rt];
               newrt=rson[newrt];rt=rson[rt];
           }
           c[newrt]=c[rt]+val;
       }
       return tmp;
    }
    int query(int lrt,int rrt,int k)
    {
        int l=1,r=s;
        while (l<r)
        {
            int mid=(l+r)>>1;
            if (c[lson[lrt]]-c[lson[rrt]]>=k){
                r=mid;
                lrt=lson[lrt];
                rrt=lson[rrt];
            }
            else
            {
                l=mid+1;
                k-=c[lson[lrt]]-c[lson[rrt]];
                lrt=rson[lrt];
                rrt=rson[rrt];
            }
        }
        return l;
    }
    int main()
    {
        while (scanf("%d%d",&n,&m)!=EOF)
        {
            //memset(c,0,sizeof c);
            tot=0;
            for (int i=1;i<=n;i++) scanf("%d",&A[i]),t[i]=A[i];
            sort(t+1,t+1+n);
            //t[0]=0;
            s=unique(t+1,t+1+n)-t-1;
            //cout<<s<<endl;
            T[n+1]=build(1,s);
            for (int i=n;i>=1;i--){
                int pos=lower_bound(t+1,t+s+1,A[i])-t;
                T[i]=update(T[i+1],pos,1);
            }
            while (m--)
            {
                int l,r,k;
                scanf("%d%d%d",&l,&r,&k);
                int ans=query(T[l],T[r+1],k);
                printf("%d
    ",t[ans]);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    C#反射(一)
    找回密码
    常用的webservice接口 .
    C# 反射应用技术
    Delphi简介
    C#程序思想简介
    如何跨线程访问window控件
    C#如何判断某个文件夹是否为共享,访问权限为只读
    Delphi基础
    Web Service接口
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3876692.html
Copyright © 2020-2023  润新知