Kth number

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10240    Accepted Submission(s): 3153


Problem Description
Give you a sequence and ask you the kth big number of a inteval.
 

 

Input
The first line is the number of the test cases. 
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere. 
The second line contains n integers, describe the sequence. 
Each of following m lines contains three integers s, t, k. 
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]
 

 

Output
For each test case, output m lines. Each line contains the kth big number.
 

 

Sample Input
1
10 1
1 4 2 3 5 6 7 8 9 0
1 3 2
 

 

Sample Output
2
 

 

Source
 题意:给你n个数  求任意区间第K大
 题解:主席树处理 主席树实际上是在线段树的基础之上,存储了在线段树更新过程中的各个历史版本。但是后一个状态的线段树与前一个状态的线段树的 在经过单点更新之后  可以发现只有一条链是不同的。
所以在更新的过程中的 增加一个当前状态的根节点  其余的能用的结点(更新未影响到的结点)继续留用。题目要求的是求任意区间 的第k大 那么对于n个数 进行离散化之后  按照从小到大的顺序
按照原序列的顺序依次添加数字到当前状态的相应位置 自增1 主席树存储当前版本。当询问 [l,r]第k大的时候 取出l ,r 两个版本的线段树 (根据root结点取出) 之后就是简单的二叉树遍历 寻找第k大的数字在
原序列中的位置。第k大用两个状态的前缀和之差来表示(因为出现的数字对应位置的值不为0)
 
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <stack>
 7 #include <queue>
 8 #include <cmath>
 9 #include <map>
10 #define ll  __int64
11 #define mod 1000000007
12 #define dazhi 2147483647
13 #define N 100005
14 using namespace  std;
15 struct chairmantree
16 {
17     int rt[20*N],ls[20*N],rs[20*N],sum[20*N];
18     int tot;
19     void init()
20     {
21         tot=0;
22     }
23     void build(int l,int r,int &pos)
24     {
25         pos=++tot;
26         sum[pos]=0;
27         if(l==r) return ;
28         int mid=(l+r)>>1;
29         build(l,mid,ls[pos]);
30         build(mid+1,r,rs[pos]);
31     }
32     void update(int p,int c,int pre,int l,int r,int &pos)
33     {
34         pos=++tot;
35         ls[pos]=ls[pre];
36         rs[pos]=rs[pre];
37         sum[pos]=sum[pre]+c;
38         if(l==r) return ;
39         int mid=(l+r)>>1;
40         if(p<=mid)
41             update(p,c,ls[pre],l,mid,ls[pos]);
42         else
43             update(p,c,rs[pre],mid+1,r,rs[pos]);
44     }
45     int query(int L,int R,int l,int r,int k)
46     {
47         if(l==r) return l;
48         int mid=(l+r)>>1;
49         int num=sum[ls[R]]-sum[ls[L]];
50         if(k<=num) return query(ls[L],ls[R],l,mid,k);
51         else return query(rs[L],rs[R],mid+1,r,k-num);
52     }
53 } tree;
54 int t;
55 int a[N],b[N];
56 int getpos(int x,int cnt)
57 {
58     int pos=lower_bound(b+1,b+cnt,x)-b;
59     return pos;
60 }
61 
62 int main()
63 {
64     scanf("%d",&t);
65     while(t--)
66     {
67         int n,m;
68         scanf("%d %d",&n,&m);
69         for(int i=1;i<=n;i++)
70         {
71             scanf("%d",&a[i]);
72             b[i]=a[i];
73         }
74         sort(b+1,b+1+n);
75         int num=unique(b+1,b+1+n)-b;
76         tree.init();
77         tree.build(1,num-1,tree.rt[0]);
78         for(int i=1;i<=n;i++)
79         {
80             int p=getpos(a[i],num);
81             tree.update(p,1,tree.rt[i-1],1,num-1,tree.rt[i]);
82         }
83         while(m--)
84         {
85             int l,r,k;
86             scanf("%d %d %d",&l,&r,&k);
87             printf("%d\n",b[tree.query(tree.rt[l-1],tree.rt[r],1,num-1,k)]);
88         }
89     }
90     return 0;
91 }