vijos P1081野生动物园 主席树求区间第K大
描述
cjBBteam拥有一个很大的野生动物园。这个动物园坐落在一个狭长的山谷内,这个区域从南到北被划分成N个区域,每个区域都饲养着一头狮子。这些狮子从北到南编号为1,2,3,…,N。每头狮子都有一个觅食能力值Ai,Ai越小觅食能力越强。饲养员cmdButtons决定对狮子进行M次投喂,每次投喂都选择一个区间[I,J],从中选取觅食能力值第K强的狮子进行投喂。值得注意的是,cmdButtons不愿意对某些区域进行过多的投喂,他认为这样有悖公平。因此cmdButtons的投喂区间是互不包含的。你的任务就是算出每次投喂后,食物被哪头狮子吃掉了。
格式
输入格式
输入第一行有两个数N和M。此后一行有N个数,从南到北描述狮子的觅食能力值。此后M行,每行描述一次投喂。第t+2的三个数I,J,K表示在第t次投喂中,cmdButtons选择了区间[I,J]内觅食能力值第K强的狮子进行投喂。
输出格式
输出有M行,每行一个整数。第i行的整数表示在第i次投喂中吃到食物的狮子的觅食能力值。
限制
各个测试点2s
提示
对于100%的数据,有1<=N<=100000,1<=M<=50000。
第一次“抄”主席树。。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 6 using namespace std; 7 8 const int M = 1000010; 9 10 struct Node{ 11 int l, r, sum; 12 }T[M*20]; 13 int T_cnt; 14 void inser(int &num, int &x, int L, int R) { 15 T[T_cnt++] = T[x]; x = T_cnt - 1; 16 ++T[x].sum; 17 if(L == R) return ; 18 int mid = (L + R) >> 1; 19 if(num <= mid) inser(num, T[x].l, L, mid); 20 else inser(num, T[x].r, mid + 1, R); 21 } 22 int query(int i, int j, int k, int L, int R) { 23 if(L == R) return L; 24 int t = T[T[j].l].sum - T[T[i].l].sum; 25 int mid = (R + L) >> 1; 26 if(k <= t) return query(T[i].l, T[j].l, k, L, mid); 27 else return query(T[i].r, T[j].r, k - t, mid + 1, R); 28 } 29 struct A{ 30 int x, idx; 31 bool operator < (const A & o)const{ 32 return x < o.x; 33 } 34 }a[M]; 35 int ranks[M], root[M]; 36 int n, m; 37 int main() { 38 T[0].l = T[0].r = T[0].sum = 0; 39 root[0] = 0; 40 while(~scanf("%d%d", &n, &m)){ 41 for(int i = 1; i <= n; i++){ 42 scanf("%d", &a[i].x); 43 a[i].idx = i; 44 } 45 sort(a+1, a+1+n); 46 for(int i = 1; i <= n; i++) ranks[a[i].idx] = i; 47 T_cnt = 1; 48 for(int i = 1; i <= n; i++){ 49 root[i] = root[i-1]; 50 inser(ranks[i], root[i], 1, n); 51 } 52 //printf("%SSS\n"); 53 while(m--){ 54 int i, j, k; 55 scanf("%d%d%d", &i, &j, &k); 56 printf("%d\n", a[query(root[i-1], root[j], k, 1, n)].x); 57 } 58 } 59 return 0; 60 }