题目链接:https://cn.vjudge.net/contest/284294#problem/A
题目大意:主席树查询区间第k小。
具体思路:主席树入门。
AC代码:
1 #include<iostream>
2 #include<stdio.h>
3 #include<algorithm>
4 #include<vector>
5 using namespace std;
6 # define ll long long
7 const int maxn = 1e5+10;
8 struct node
9 {
10 int sum;
11 int l,r;
12 } tree[maxn*80];
13 int sto[maxn],root[maxn];
14 vector<int>q;
15 int tot;
16 void init()
17 {
18 tot=0;
19 root[0]=0;
20 }
21 int get_id(int t)
22 {
23 return lower_bound(q.begin(),q.end(),t)-q.begin()+1;
24 }
25 int add(int pre)
26 {
27 int t=++tot;
28 tree[t].sum=tree[pre].sum+1;
29 tree[t].l=tree[pre].l;
30 tree[t].r=tree[pre].r;
31 return t;
32 }
33 void update(int &o,int pre,int l,int r,int pos)
34 {
35 o=add(pre);
36 if(l==r)return ;
37 int m=(l+r)>>1;
38 if(pos<=m)update(tree[o].l,tree[o].l,l,m,pos);
39 else update(tree[o].r,tree[o].r,m+1,r,pos);
40 }
41 int query(int st,int ed,int l,int r,int k){
42 if(l==r)return r;
43 int sum=tree[tree[ed].l].sum-tree[tree[st].l].sum;
44 int m=(l+r)>>1;
45 if(k<=sum)return query(tree[st].l,tree[ed].l,l,m,k);
46 else return query(tree[st].r,tree[ed].r,m+1,r,k-sum);
47 }
48 int main()
49 {
50 int n,m;
51 while(~scanf("%d %d",&n,&m))
52 {
53 init();
54 for(int i=1; i<=n; i++)
55 {
56 scanf("%d",&sto[i]);
57 q.push_back(sto[i]);
58 }
59 sort(q.begin(),q.end());
60 q.erase(unique(q.begin(),q.end()),q.end());
61 int num=q.size();
62 for(int i=1; i<=n; i++)
63 {
64 update(root[i],root[i-1],1,num,get_id(sto[i]));
65 }
66 int t1,t2,k;
67 while(m--){
68 scanf("%d %d %d",&t1,&t2,&k);
69 printf("%d\n",q[query(root[t1-1],root[t2],1,num,k)-1]);
70 }
71 }
72 return 0;
73 }