Chairman of the tree [may persist segment tree] study notes

Word algorithm:

Chairman of the tree, also known as persistable tree line, is a historical version based on prefix and save ideas that can support a single point of modification, query the value of a location at a certain historical versions of data structure.

The main idea:

For our bold proposition above, we first consider the practice of violence:

For each state history, the establishment of a segment tree maintenance information current status.

Then you will find that the state transition and space consumption are very large, (edge \ (MLE \) side \ (TLE \) how it feels like) you will get a \ (TM (LE) ^ 2 \) results.

We then consider how to accelerate the transfer of state and compression space.

Taking into account only changes every time a modified single-point point, its impact is only at this point to the root of this chain, while other states are unchanged: So we do not need to update each node again, and is a new node has been altered, and then to the upper node of a tree, so that each time a state transition is compressed into \ (log (n) \) complexity, empathy space.

example:

The feeling is not very good against air or speak, so we look at a question:

Given a sequence of N integers will query its small K values ​​within the range specified for the closed interval.

Lift the Chairman of the tree, almost everyone first thought was such a question. For Interval \ (K \) large, we established weights segment tree (i.e. the weight as the target segment tree, node weights represents the number of occurrences), the state transition using the above method, the \ (I \) trees weights segment tree maintenance interval \ ([1, i] \ ) information, each time using a query prefix and thought as the difference obtained intermediate state \ ([L, R & lt] \) , then look in the tree, if the total number of left subtree elements \ (\ geq k \) , description of the \ (k \) large in the left sub-tree, then into the left sub-tree recursively, otherwise go to the right subtree recursively, note into the right subtree recursively time the new \ (k \) to lose the left subtree \ (size \) .

Chairman of the tree of spatial complexity is \ (nlog (n) \) level, we generally will directly open \ (n << 5 \) spaceOr will fly to RE. Although the space consumption is still very large, but compared to the violence, it is still a superior approach.

Digression:

Chairman of sustainable thinking tree on the other algorithm has also been a corresponding application, such as an array can be persistent, be persistent Trie and so on.

So there are so many cancer data structure

Code:

#include<bits/stdc++.h>
#define N (200000 + 5)
using namespace std;
inline int read() {
    int cnt = 0, f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
    while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();}
    return cnt * f;
}
int a[N], b[N * 2], n, m, q, rt[N], tot;
int x, y, k, res;
void Discretize() {
    sort (b + 1, b + n + 1);
    q = unique(b + 1, b + n + 1) - b - 1;
    for (register int i = 1; i <= n; i++) 
        a[i] = lower_bound(b + 1, b + q + 1, a[i]) - b;
}
struct node{
    int l, r, sum;
    #define l(p) tree[p].l
    #define r(p) tree[p].r
    #define sum(p) tree[p].sum
}tree[N * 18];

void build(int &p, int l, int r) {
    p = ++tot;
    if (l == r) return;
    int mid = (l + r) >> 1;
    build (l(p), l, mid);
    build (r(p), mid + 1, r);
}

void insert(int &p, int l, int r, int last, int pos) {
    p = ++tot;
    l(p) = l(last), r(p) = r(last);
    sum(p) = sum(last) + 1;
    if (l == r) return;
    int mid = (l + r) >> 1;
    if (pos <= mid) insert(l(p), l, mid, l(last), pos);
    else insert(r(p), mid + 1, r, r(last), pos);
}

int query (int L, int R, int l, int r, int k) {
    if (l == r) return l;
    int mid = (l + r) >> 1;
    int cnt = sum(l(R)) - sum(l(L));
    if (k <= cnt) return query(l(L), l(R), l, mid, k);
    else return query(r(L), r(R), mid + 1, r, k - cnt);
}

int main() {
    n = read(); m = read();
    for (register int i = 1; i <= n; i++) a[i] = b[i] = read();
    Discretize();
    build(rt[0], 1, q);
    for (register int i = 1; i <= n; ++i) insert(rt[i], 1, q, rt[i - 1], a[i]);
    while (m--) {
        x = read(), y = read(), k = read();
        res = query(rt[x - 1], rt[y], 1, q, k);
        printf("%d\n", b[res]);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/kma093/p/11141175.html