1. 程式人生 > >POJ_2104 K-th Number 【主席樹】

POJ_2104 K-th Number 【主席樹】

uil 持久化 就是 lan pan lower 構造 宋體 之前

一 題面

  K-th Number

二 分析

  第一個主席樹的題,感觸蠻多吧,幾個關鍵點就是可持久化數據結構,這裏的主席樹其實就是保留了之前各個版本的權值線段樹,然後利用權值線段樹和歷史版本可以進行相加減的優勢,實現了第K小。

三 AC代碼

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int MAXN = 1e5 + 15
; 8 const int N = MAXN * 30; 9 10 int n, m, tot, len; 11 int a[MAXN], b[MAXN]; 12 int T[N], lson[N], rson[N], sum[N]; 13 //進行離散化 14 int getID(int val) 15 { 16 return lower_bound(b + 1, b + n + 1, val) - b; 17 } 18 //初始化,如果追求速度,可以進行優化 19 void build(int &root, int l, int r) 20 { 21 root = tot++;
22 if(l == r) 23 return; 24 sum[root] = 0; 25 int mid = (l + r) >> 1; 26 build(lson[root], l, mid); 27 build(rson[root], mid + 1, r); 28 } 29 //構造新版本的權值線段樹 30 void update(int &cur, int pre, int l, int r, int val) 31 { 32 cur = tot++; 33 lson[cur] = lson[pre];
34 rson[cur] = rson[pre]; 35 sum[cur] = sum[pre] + 1; 36 if(l == r) return; 37 int mid = (l + r) >> 1; 38 if(val <= mid) update(lson[cur], lson[pre], l, mid, val); 39 else update(rson[cur], rson[pre], mid + 1, r, val); 40 } 41 //詢問第K小 42 int query(int x, int y, int l, int r, int k) 43 { 44 if(l == r) 45 return l; 46 int mid = (l + r) >> 1; 47 int res = sum[lson[y]] - sum[lson[x]]; 48 if(res >= k) return query(lson[x], lson[y], l, mid, k); 49 else return query(rson[x], rson[y], mid + 1, r, k - res); 50 } 51 int main() 52 { 53 scanf("%d %d", &n, &m); 54 for(int i = 1; i <= n; i++) 55 { 56 scanf("%d", &a[i]); 57 b[i] = a[i]; 58 } 59 sort(b + 1, b + n + 1); 60 len = unique(b + 1, b + n + 1) - b - 1; 61 tot = 0; 62 build(T[0], 1, len); 63 for(int i = 1; i <= n; i++) 64 { 65 update(T[i], T[i-1], 1, len, getID(a[i])); 66 } 67 while(m--) 68 { 69 int l, r, k; 70 scanf("%d %d %d", &l, &r, &k); 71 printf("%d\n", b[query(T[l - 1], T[r], 1, len, k)]); 72 } 73 return 0; 74 }

POJ_2104 K-th Number 【主席樹】