[Luogu] 树

Posted xayata

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Luogu] 树相关的知识,希望对你有一定的参考价值。

https://www.luogu.org/problemnew/show/P4092

树剖 + 线段树区间修改,单点查询

#include <bits/stdc++.h>

using namespace std;
const int N = 1e5 + 10;

inline int read() {int ret; scanf("%d", &ret); return ret;}

int n, T;
int now = 1, head[N];
struct Node {int u, v, nxt;} G[N << 1];
int fa[N], top[N], size[N], son[N], deep[N], lst[N], rst[N], tree[N], tim;
int F[N << 2];
int Answer;

struct Node_A{
    inline void Add(int u, int v) {G[now].v = v; G[now].nxt = head[u]; head[u] = now ++;}
    void Dfs_1(int u, int f_, int dep) {
        fa[u] = f_; deep[u] = dep; size[u] = 1;
        for(int i = head[u]; ~ i; i = G[i].nxt) {
            int v = G[i].v;
            if(v != f_) {
                Dfs_1(v, u, dep + 1);
                size[u] += size[v];
                if(size[v] > size[son[u]]) son[u] = v;
            }
        }
    }
    void Dfs_2(int u, int tp) {
        top[u] = tp; tree[u] = ++ tim; lst[u] = tim;
        if(!son[u]) {rst[u] = tim; return ;}
        Dfs_2(son[u], tp);
        for(int i = head[u]; ~ i; i = G[i].nxt) {
            int v = G[i].v;
            if(v != fa[u] and v != son[u]) Dfs_2(v, v);
        }
        rst[u] = tim;
    }
    #define lson jd << 1
    #define rson jd << 1 | 1
    void Build_tree(int l, int r, int jd) {
        if(l == r) {F[jd] = 1; return ;}
        int mid = (l + r) >> 1;
        Build_tree(l, mid, lson);
        Build_tree(mid + 1, r, rson);
    }
    void Down(int jd) {
        int imp = F[jd];
        if(deep[imp] > deep[F[lson]]) F[lson] = imp;
        if(deep[imp] > deep[F[rson]]) F[rson] = imp;
        F[jd] = 0;
    }
    void Sec_G(int l, int r, int jd, int x, int y, int g) {
        if(x <= l and r <= y) {
            if(deep[F[jd]] < deep[g]) F[jd] = g;
            return ;
        }
        if(F[jd]) Down(jd);
        int mid = (l + r) >> 1;
        if(x <= mid) Sec_G(l, mid, lson, x, y, g);
        if(y > mid)  Sec_G(mid + 1, r, rson, x, y, g);
    }
    void Poi_A(int l, int r, int jd, int x) {
        if(l == r) {Answer = F[jd]; return ;}
        if(F[jd]) Down(jd);
        int mid = (l + r) >> 1;
        if(x <= mid) Poi_A(l, mid, lson, x);
        else Poi_A(mid + 1, r, rson, x);
    }
}Tj;

int main() {
    n = read(); T = read();
    for(int i = 1; i <= n; i ++) head[i] = -1;
    for(int i = 1; i < n; i ++) {
        int u = read(), v = read();
        Tj.Add(u, v); Tj.Add(v, u);
    }
    Tj.Dfs_1(1, 0, 1);
    Tj.Dfs_2(1, 1);
    Tj.Build_tree(1, n, 1);
    while(T --) {
        string s; cin >> s;
        if(s[0] == C) {int x = read(); Tj.Sec_G(1, n, 1, lst[x], rst[x], x);}
        else {int x = read(); Tj.Poi_A(1, n, 1, tree[x]); cout << Answer << "\n";}
    }
    return 0;
}
/*
5 5 
1 2 
1 3 
2 4 
2 5 
Q 2 
C 2 
Q 2 
Q 5 
Q 3
*/

 

以上是关于[Luogu] 树的主要内容,如果未能解决你的问题,请参考以下文章

Luogu_P2536 [AHOI2005]病毒检测 trie树+dfs

Luogu4899 IOI2018 Werewolf 主席树Kruskal重构树

luogu_1550题解打井(最小生成树)

线段树模板1 [Luogu P3372]

luogu3373线段树2..支持区间加值和乘值的线段树

LUOGU P3834 模板可持久化线段树 1(主席树)