1. 程式人生 > >POJ 2104 K-th Number

POJ 2104 K-th Number

poj 2104 working lan 只需要 please lin absolut input nlogn

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\n",b[ask(t[x-1],t[y],k)]);
        }
    }
    return 0;
}

POJ 2104 K-th Number