主席树区间第K大
主席树的实质其实还是一颗线段树, 然后每一次修改都通过上一次的线段树,来添加新边,使得每次改变就改变logn个节点,很多节点重复利用,达到节省空间的目的。
1.不带修改的区间第K大。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const LL mod = 1e9+7; 16 const int N = 1e5+10; 17 struct Node{ 18 int l, r; 19 int num; 20 }tree[N*20]; 21 int tot = 0; 22 int root[N]; 23 int Rank[N]; 24 int b[N]; 25 struct N{ 26 int a; 27 int id; 28 bool operator < (const N & x) const{ 29 return a < x.a; 30 } 31 }A[N]; 32 33 int Build(int l, int r){ 34 int now = ++tot; 35 tree[now].num = 0; 36 if(l == r) return now; 37 int m = l+r >> 1; 38 tree[now].l = Build(l,m); 39 tree[now].r = Build(m+1,r); 40 return now; 41 } 42 int update(int pre, int l, int r, int k){ 43 int now = ++tot; 44 tree[now].num = 0; 45 tree[now].l = tree[pre].l; 46 tree[now].r = tree[pre].r; 47 if(l < r) { 48 int m = l+r >> 1; 49 if(k <= m) tree[now].l = update(tree[pre].l ,l, m, k); 50 else tree[now].r = update(tree[pre].r, m+1, r, k); 51 tree[now].num = tree[tree[now].l].num + tree[tree[now].r].num; 52 } 53 else tree[now].num = 1; 54 return now; 55 } 56 int query(int u, int v, int l, int r,int k){ 57 if(l == r) return l; 58 int m = l+r >> 1; 59 int num1 = tree[tree[v].l].num - tree[tree[u].l].num; 60 if(num1 >= k) return query(tree[u].l, tree[v].l, l, m, k); 61 return query(tree[u].r, tree[v].r, m+1,r,k-num1); 62 } 63 int main(){ 64 ///Fopen; 65 int t, n, m; 66 scanf("%d", &t); 67 while(t--){ 68 scanf("%d%d", &n, &m); 69 for(int i = 1; i <= n; i++){ 70 scanf("%d", &A[i].a); 71 A[i].id = i; 72 } 73 sort(A+1, A+1+n); /// 离散化 74 int t = 0; 75 A[0].a = -1; 76 for(int i = 1; i <= n; i++){ 77 if(A[i].a != A[i-1].a) t++, Rank[t] = A[i].a; 78 b[A[i].id] = t; 79 } 80 tot = 0; 81 root[0] = Build(1,t); 82 for(int i = 1; i <= n; i++) 83 root[i] = update(root[i-1], 1, t, b[i]); 84 while(m--){ 85 int l, r, k; 86 scanf("%d%d%d", &l, &r, &k); 87 printf("%d\n", Rank[query(root[l-1], root[r],1, t, k)]); 88 } 89 } 90 return 0; 91 } 92 /* 93 1 94 10 1 95 1 4 2 3 5 6 7 8 9 0 96 1 3 2 97 98 */