【静态主席树】POJ2104-K-th Number

求区间第k大。裸线段树。

莫队版本:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #define lson l,m
 7 #define rson m+1,r
 8 using namespace std;
 9 const int MAXN=100000+50;
10 int sum[MAXN<<5],L[MAXN<<5],R[MAXN<<5];
11 int a[MAXN],hash[MAXN],T[MAXN],tot=0;
12 int m,n,d;
13 
14 int build(int l,int r)
15 {
16     int rt=++tot;
17     sum[rt]=0;
18     if (l<r)
19     {
20         int m=(l+r)>>1;
21         L[rt]=build(lson);
22         R[rt]=build(rson);
23     }
24     return rt;
25 } 
26 
27 int update(int pre,int l,int r,int x)
28 {
29     int rt=++tot;
30     L[rt]=L[pre],R[rt]=R[pre],sum[rt]=sum[pre]+1;
31     if (l!=r)
32     {
33         int m=(l+r)>>1;
34         if (x<=m) L[rt]=update(L[rt],lson,x);
35             else R[rt]=update(R[rt],rson,x);
36     }
37     return rt;
38 }
39 
40 int query(int lrt,int rrt,int l,int r,int k)
41 {
42     if (l==r) return l;
43     int num=sum[L[rrt]]-sum[L[lrt]];
44     
45     int m=(l+r)>>1;
46     if(num>=k)
47         return query(L[lrt], L[rrt], lson, k);
48     else
49         return query(R[lrt], R[rrt], rson, k-num);
50 }
51 
52 void init()
53 {
54     scanf("%d%d",&n,&m);
55     for (int i=1;i<=n;i++)
56     {
57         scanf("%d",&a[i]);
58         hash[i]=a[i];
59     }
60     sort(hash+1,hash+n+1);
61     d=unique(hash+1,hash+n+1)-hash-1;
62     T[0]=build(1,n);
63     for (int i=1;i<=n;i++)
64     {
65         int x=lower_bound(hash,hash+d+1,a[i])-hash;
66         T[i]=update(T[i-1],1,d,x);
67     } 
68 }
69 
70 void solve()
71 { 
72     for (int i=0;i<m;i++)
73     {
74         int l,r,k;
75         scanf("%d%d%d",&l,&r,&k);
76         int x=query(T[l-1],T[r],1,d,k);
77         printf("%d
",hash[x]);
78     }
79 }
80 
81 int main()
82 {
83     init();
84     solve();
85     return 0;
86 }
原文地址:https://www.cnblogs.com/iiyiyi/p/5762597.html