可持久化线段树初步

可持久化线段树是可以查询历史版本的数据结构,比如说查询区间第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 }
View Code

 

    树上第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 }
View Code

 

posted @ 2015-11-27 00:44  y7070  阅读(354)  评论(0编辑  收藏  举报