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]
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 }