zoukankan      html  css  js  c++  java
  • POJ 2104 K-th Number

    Time Limit: 20000MS   Memory Limit: 65536K
    Total Submissions: 59481   Accepted: 20727
    Case Time Limit: 2000MS

    Description

    You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment. 
    That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?" 
    For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.

    Input

    The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000). 
    The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given. 
    The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).

    Output

    For each question output the answer to it --- the k-th number in sorted a[i...j] segment.

    Sample Input

    7 3
    1 5 2 6 3 7 4
    2 5 3
    4 4 1
    1 7 3

    Sample Output

    5
    6
    3

    Hint

    This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.

    Source

     

    主席树(函数式线段树)裸题

    主席树是一种离线数据结构,是由很多棵线段树组成的。

    第i棵树代表第i个数出现前的情况

    每个线段存数字的出现次数 

    听起来 

    肯定会MLE !

    但是我们发现i和i-1的某些节点完全相同 所以只需要借用以前的点就可以 ,不需要新建。

    那么如果要询问i-j之间数字出现的次数怎么办呢?

    因为每一棵线段树的区间都是相同的,所以要求l-r之间的数字的出现次数只要用前r位出现的次数减去前l-1位出现的次数,就是ans

    但是如果有修改操作怎么办?

    如果沿用上面的做法,那么修改操作是O(nlogn)的,查询是O(1)的,修改要花好长时间。。。

    前缀和联想到了树状数组,那么将前缀和用树状数组维护的话修改是O(logn*logn),查询时O(logn),查询的时间虽然变长,但是修改的时间缩短许多!!

    注意:

    函数式线段树的数组要开大一点!!

    转载自http://blog.csdn.net/regina8023/article/details/41910615

     

    现在还不会主席树,先敲下模板,以后会用到的

    本题没涉及到修改 

    屠龙宝刀点击就送

    #include <algorithm>
    #include <cstdio>
    #define N 105000
    
    using std::sort;
    using std::unique;
    using std::lower_bound;
    
    struct cmt
    {
        int l,r,Size;
    }tr[N*20];
    int a[N],b[N],t[N],tot,Size,n,m,T;
    int build(int l,int r)
    {
        int root=++tot;
        tr[root].Size=0;
        if(l==r) return root;
        int mid=(l+r)>>1;
        tr[root].l=build(l,mid);
        tr[root].r=build(mid+1,r);
        return root;
    }
    int update(int rt,int x)
    {
        int now=++tot;
        int tmp=now;
        tr[now].Size=tr[rt].Size+1;
        for(int mid,l=1,r=Size;l<=r;)
        {
            mid=(l+r)>>1;
            if(x<=mid)
            {
                tr[now].l=++tot;
                tr[now].r=tr[rt].r;
                rt=tr[rt].l;
                now=tot;
                r=mid-1;
            }
            else
            {
                tr[now].l=tr[rt].l;
                tr[now].r=++tot;
                rt=tr[rt].r;
                now=tot;
                l=mid+1;
            }
            tr[now].Size=tr[rt].Size+1;
        }
        return tmp;
    }
    int ask(int lx,int rx,int k)
    {
        int l=1,r=Size;
        for(int mid;l<=r;)
        {
            mid=(l+r)>>1;
            if(tr[tr[rx].l].Size-tr[tr[lx].l].Size>=k)
            {
                rx=tr[rx].l;
                lx=tr[lx].l;
                r=mid-1;
            }
            else
            {
                k-=tr[tr[rx].l].Size-tr[tr[lx].l].Size;
                rx=tr[rx].r;
                lx=tr[lx].r;
                l=mid+1;
            }
        }
        return l;
    }
    int main()
    {
        scanf("%d",&T);
        for(;T--;)
        {
            tot=0;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i];
            sort(b+1,b+1+n);
            Size=unique(b+1,b+1+n)-b-1;
            t[0]=build(1,Size);
            for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+1+Size,a[i])-b;
            for(int i=1;i<=n;++i)
            t[i]=update(t[i-1],a[i]);
            for(int x,y,k;m--;)
            {
                scanf("%d%d%d",&x,&y,&k);
                printf("%d
    ",b[ask(t[x-1],t[y],k)]);
            }
        }
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    java.lang.IllegalStateException: Failed to load property source from location 'classpath:/application.yml'
    generate failed: Cannot resolve classpath entry: mysql-connector-java-5.1.38.jar
    Spring boot 零配置开发微服务
    【ABAP系列】SAP ABAP BAPI_REQUISITION_CREATE创建采购申请
    【ABAP系列】SAP ABAP 字符编码与解码、Unicode
    【ABAP系列】ABAP CL_ABAP_CONV_IN_CE
    【Fiori系列】浅谈SAP Fiori的设计美感与发展历程
    【Fiori系列】为什么SAP Fiori活的如此精致
    【ABAP系列】SAP ABAP下载带密码的Excel文件
    【ABAP系列】SAP ABAP 高级业务应用程序编程(ABAP)
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7404393.html
Copyright © 2011-2022 走看看