[POJ 2104]K-th Number

danihao123 posted @ 2016年2月11日 10:42 in 题解 with tags POJ 区间K大 主席树 , 651 阅读
转载请注明出处:http://danihao123.is-programmer.com/

我擦终于A了这题了!

主席树坑点多……

最好不要写指针主席树,不然容易TLE……(自带常数?

并且注意,一定要把数组开大,开大,再开大,重要的事情说三遍

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=100001,maxnode=maxn*20;
int sumv[maxnode];
int lc[maxnode];
int rc[maxnode];
int root[maxn];
int A[maxn];
int A2[maxn];
int size,tot=0;
int build_tree(int L,int R){
    ++tot;
    if(L==R)
        return tot;
    int ans=tot,M=L+(R-L)/2;
    lc[ans]=build_tree(L,M);
    rc[ans]=build_tree(M+1,R);
    return ans;
}
int p;
int update(int o,int L,int R){
    int roo=++tot;
    sumv[roo]=sumv[o];
    lc[roo]=lc[o];
    rc[roo]=rc[o];
    if(R>L){
        int M=L+(R-L)/2;
        if(p<=M)
            lc[roo]=update(lc[tot],L,M);
        else
            rc[roo]=update(rc[tot],M+1,R);
    }
    sumv[roo]++;
    return roo;
}
int query(int lo,int ro,int L,int R,int k){
    if(L==R)
        return L;
    int M=L+(R-L)/2,lc_siz=sumv[lc[ro]]-sumv[lc[lo]];
    if(k<=lc_siz)
        return query(lc[lo],lc[ro],L,M,k);
    else
        return query(rc[lo],rc[ro],M+1,R,k-lc_siz);
}
void init_tree(int n){
    register int i;
    sort(A2,A2+n);
    size=unique(A2,A2+n)-A2;
    root[0]=build_tree(1,size);
    for(i=1;i<=n;i++){
        p=lower_bound(A2,A2+size,A[i-1])-A2+1;
        root[i]=update(root[i-1],1,size);
    }
}
int main(){
    int n,m,u,v,k;
    register int i;
    scanf("%d%d",&n,&m);
    for(i=0;i<n;i++){
        scanf("%d",&A[i]);
        A2[i]=A[i];
    }
    init_tree(n);
    for(i=0;i<m;i++){
        scanf("%d%d%d",&u,&v,&k);
        printf("%d\n",A2[query(root[u-1],root[v],1,size,k)-1]);
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter