2665 Kth number (靜態區間第k大)
阿新 • • 發佈:2019-02-04
Give you a sequence and ask you the kth big number of a inteval.
InputThe 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]
OutputFor each test case, output m lines. Each line contains the kth big number.
Sample Input
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]
1
10 1
1 4 2 3 5 6 7 8 9 0
1 3 2
Sample Output
2
#include<iostream> #include<algorithm> #include<stdlib.h> #include<memory.h> #include<queue> using namespace std; const int MAXN=100101; int ls[MAXN*20];//記錄左兒子 int rs[MAXN*20];//記錄右兒子 int sum[MAXN*20];//記錄區間中包含數的個數 int num[MAXN];//原陣列 int sorted[MAXN];//排序並去重後的陣列 int T[MAXN];//記錄第i次操作的根節點(可持久化線段樹) int n,m,tot=0;//動態開點 //建立一棵空樹,初始狀態為一棵空樹 void build(int l,int r,int &x){ x=++tot; sum[x]=0; if(l==r) return; int m=(l+r)/2; build(l,m,ls[x]); build(m+1,r,rs[x]); } //單點更新 void update(int last,int p,int l,int r,int &x){ x=++tot; ls[x]=ls[last]; rs[x]=rs[last]; sum[x]=sum[last]+1; if(l==r) return; int m=(l+r)/2; if(p<=m) update(ls[last],p,l,m,ls[x]); else update(rs[last],p,m+1,r,rs[x]); } int query(int s,int t,int l,int r,int k){ if(l==r) return l; int m=(l+r)/2; int cnt=sum[ls[t]]-sum[ls[s]]; if(k<=cnt) return query(ls[s],ls[t],l,m,k); return query(rs[s],rs[t],m+1,r,k-cnt); } int main(){ int t; scanf("%d",&t); while(t--){ tot=0; int x,y,z; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&sorted[i]); num[i]=sorted[i]; } sort(sorted+1,sorted+n+1); int cnt=unique(sorted+1,sorted+n+1)-sorted-1; build(1,cnt,T[0]); for(int i=1;i<=n;i++) num[i]=lower_bound(sorted+1,sorted+cnt+1,num[i])-sorted;//把原陣列修改為在排序過後的陣列的下標 //因為線段樹存的值是數字出現的個數 for(int i=1;i<=n;i++) update(T[i-1],num[i],1,cnt,T[i]); for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); printf("%d\n",sorted[query(T[x-1],T[y],1,cnt,z)]); } } return 0; }