可持久化线段树初步
可持久化线段树是可以查询历史版本的数据结构,比如说查询区间第k大的数,那么我们需要查询到1-r 和 1- (l - 1) 数据的分布情况,以完成查询。
2015年11月25日
模板题 poj2104
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define rep(i, a, b) for (int i = a; i <= b; i++) 5 #define REP(i, a, b) for (int i = a; i < b; i++) 6 #define drep(i, a, b) for (int i = a; i >= b; i--) 7 #define mp make_pair 8 #define pb push_back 9 #define clr(x) memset(x, 0, sizeof(x)) 10 #define xx first 11 #define yy second 12 using namespace std; 13 typedef long long i64; 14 typedef pair<int, int> pii; 15 const int inf = ~0U>>1; 16 const i64 INF = ~0ULL >> 1; 17 //********************************* 18 19 const int maxn = 100005, maxm = 2060965; 20 int Sum[maxm]; 21 int Lson[maxm], Rson[maxm]; 22 23 int read() { 24 int l = 1, s = 0; 25 char ch = getchar(); 26 while (ch < '0' || ch > '9') { if (ch == '-') l = -1; ch = getchar(); } 27 while (ch >= '0' && ch <= '9') { s = (s << 1) + (s << 3) + ch - '0'; ch = getchar(); } 28 return l * s; 29 } 30 31 int totnode; 32 void build(int x, int &y, int l, int r, int v) { 33 Sum[y = ++totnode] = Sum[x] + 1; 34 if (l == r) return; 35 int mid = l + r >> 1; 36 if (v <= mid) { 37 Rson[y] = Rson[x]; 38 build(Lson[x], Lson[y], l, mid, v); 39 } 40 else { 41 Lson[y] = Lson[x]; 42 build(Rson[x], Rson[y], mid + 1, r, v); 43 } 44 } 45 46 int query(int x, int y, int l, int r, int k) { 47 if (l == r) return l; 48 int mid = l + r >> 1, tmp = Sum[Lson[y]] - Sum[Lson[x]]; 49 if (tmp >= k) return query(Lson[x], Lson[y], l, mid, k); 50 else return query(Rson[x], Rson[y], mid + 1, r, k - tmp); 51 } 52 53 int val[maxn], hsh[maxn], root[maxn]; 54 int main() { 55 int n, m; 56 n = read(), m = read(); 57 rep(i, 1, n) val[i] = read(), hsh[i] = val[i]; 58 sort(hsh + 1, hsh + 1 + n); int cd = unique(hsh + 1, hsh + 1 + n) - (hsh + 1); 59 rep(i, 1, n) val[i] = lower_bound(hsh + 1, hsh + 1 + cd, val[i]) - hsh; 60 61 int cnt = cd; 62 for (int i = 1; i <= n; i++) 63 build(root[i - 1], root[i], 1, cnt, val[i]); 64 65 for (int i = 1; i <= m; i++) { 66 int x, y, k; x = read(), y = read(), k = read(); 67 printf("%d\n", hsh[query(root[x - 1], root[y], 1, cnt, k)]); 68 } 69 70 return 0; 71 }
树上第k大 清橙1501 树
以每一条链建立线段树,然后用第一个点减去lca加上第二个点减去lca上面那个点的值来查询,注意,线段树里开的是每个区间有多少个数。
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define REP(i, a, b) for (int i = a; i < b; i++) 4 #define drep(i, a, b) for (int i = a; i >= b; i--) 5 #define pb push_back 6 #define mp make_pair 7 #define xx first 8 #define yy second 9 using namespace std; 10 typedef long long i64; 11 typedef pair<int, int> pii; 12 const int inf = ~0U >> 1; 13 const i64 INF = ~0ULL >> 1; 14 //***************************** 15 const int maxn = 200005, maxm = 1700005; 16 struct Ed { 17 int u, v, nx; Ed() {} 18 Ed(int _u, int _v, int _nx) : 19 u(_u), v(_v), nx(_nx) {} 20 } E[maxn << 1]; 21 int G[maxn], ccnt; 22 void addedge(int u, int v) { 23 E[ccnt] = Ed(u, v, G[u]); 24 G[u] = ccnt++; 25 } 26 int dep[maxn], fa[maxn][18]; 27 bool vis[maxn]; 28 int val[maxn]; 29 void build_lca(int x) { 30 vis[x] = 1; 31 rep(i, 1, 17) { 32 if (1 << i > dep[x]) break; 33 fa[x][i] = fa[fa[x][i - 1]][i - 1]; 34 } 35 for (int i = G[x]; i != -1; i = E[i].nx) if (!vis[E[i].v]) { 36 dep[E[i].v] = dep[x] + 1; 37 fa[E[i].v][0] = x; 38 build_lca(E[i].v); 39 } 40 } 41 int ask(int l, int r) { 42 if (dep[l] < dep[r]) swap(l, r); 43 int t = dep[l] - dep[r]; 44 drep(i, 17, 0) { 45 if (t & 1 << i) { 46 l = fa[l][i]; 47 } 48 } 49 if (l == r) return l; 50 drep(i, 17, 0) { 51 if (fa[l][i] != fa[r][i]) { 52 l = fa[l][i], r = fa[r][i]; 53 } 54 } 55 return fa[l][0]; 56 } 57 int Sum[maxm], Lson[maxm], Rson[maxm], ndtot, root[maxm]; 58 void build(int x, int &y, int l, int r, int v) { 59 Sum[y = ++ndtot] = Sum[x] + 1; 60 if (l == r) return; 61 int mid = l + r >> 1; 62 if (v <= mid) { 63 Rson[y] = Rson[x]; 64 build(Lson[x], Lson[y], l, mid, v); 65 } 66 else { 67 Lson[y] = Lson[x]; 68 build(Rson[x], Rson[y], mid + 1, r, v); 69 } 70 } 71 int cnt; 72 void dfs(int x, int father) { 73 build(root[father], root[x], 1, cnt, val[x]); 74 for (int i = G[x]; i != -1; i = E[i].nx) 75 if (E[i].v != father) dfs(E[i].v, x); 76 } 77 int query(int x1, int y1, int x2, int y2, int l, int r, int k) { 78 if (l == r) return l; 79 int mid = l + r >> 1, tmp = Sum[Lson[x1]] - Sum[Lson[y1]] + Sum[Lson[x2]] - Sum[Lson[y2]]; 80 if (tmp >= k) return query(Lson[x1], Lson[y1], Lson[x2], Lson[y2], l, mid, k); 81 else return query(Rson[x1], Rson[y1], Rson[x2], Rson[y2], mid + 1, r, k - tmp); 82 } 83 int solve(int x, int y, int lca, int op) { 84 int st1 = lca, st2 = fa[lca][0]; 85 int tot = Sum[root[x]] - Sum[root[st1]] + Sum[root[y]] - Sum[root[st2]]; 86 int k; 87 if (op == 1) k = 1; 88 else if (op == 2) k = tot; 89 else { k = tot >> 1; k++; } 90 return query(root[x], root[st1], root[y], root[st2], 1, cnt, k); 91 } 92 int read() { 93 int l = 1, s = 0; 94 char ch = getchar(); 95 while (ch < '0' || ch > '9') { if (ch == '-') l = -1; ch = getchar(); } 96 while (ch >= '0' && ch <= '9') { s = (s << 1) + (s << 3) + ch - '0'; ch = getchar(); } 97 return l * s; 98 } 99 int hsh[maxn]; 100 int main() { 101 int n, m; 102 scanf("%d%d", &n, &m); 103 memset(G, -1, sizeof(G)); 104 rep(i, 1, n) val[i] = hsh[i] = read(); 105 sort(hsh + 1, hsh + 1 + n); int cd = unique(hsh + 1, hsh + 1 + n) - (hsh + 1); 106 rep(i, 1, n) val[i] = lower_bound(hsh + 1, hsh + 1 + cd, val[i]) - hsh; 107 REP(i, 1, n) { 108 int x, y; 109 x = read(), y = read(), addedge(x, y), addedge(y, x); 110 } 111 build_lca(1); 112 cnt = cd; 113 dfs(1, 0); 114 rep(i, 1, m) { 115 int op, x, y; 116 op = read(), x = read(), y = read(); 117 int t = ask(x, y); 118 printf("%d\n", hsh[solve(x, y, t, op)]); 119 } 120 return 0; 121 }