HDU 3974 Assign the task(dfs序建线段树)

题目链接

题目大意

  现有一棵树,初始所有点都没有染色。有以下操作:
  1. 节点x及其所有子孙颜色都变更为k。
  2. 要求你回答节点x的颜色。

解题思路

  先跑一个dfs序,每棵子树的根结点一定最先被访问,最后一个叶子结点最后被访问,且中间的结点都属于这棵子树。

代码

const int maxn = 2e5+10;
int n, m, in[maxn], last[maxn], num[maxn], tot;
vector<int> e[maxn];
int dfs(int u, int p) {
    num[u] = ++tot;
    last[u] = u;
    for (auto v : e[u])
        if (v!=p) last[u] = dfs(v, u);
    return last[u];
}
struct Tree {
    int l, r, col, lz;
} tree[maxn<<2];
void build(int rt, int l, int r) {
    tree[rt].l = l, tree[rt].r = r; tree[rt].col = -1, tree[rt].lz = 0;
    if (l==r) return;
    int mid = (l+r)>>1;
    build(rt<<1, l, mid);
    build(rt<<1|1, mid+1, r);
}
inline void push_down(int rt) {
    if (tree[rt].lz) {
        tree[rt<<1].lz = tree[rt<<1|1].lz = tree[rt].lz;
        tree[rt<<1].col = tree[rt<<1|1].col = tree[rt].lz;
        tree[rt].lz = 0;
    }
}
void update(int rt, int l, int r, int col) {
    if (tree[rt].l>=l && tree[rt].r<=r) {
        tree[rt].col = tree[rt].lz = col;
        return;
    }
    push_down(rt);
    int mid = (tree[rt].l+tree[rt].r)>>1;
    if (l<=mid) update(rt<<1, l, r, col);
    if (r>mid) update(rt<<1|1, l, r, col);
}
int ask(int rt, int pos) {
    if (tree[rt].l==tree[rt].r) return tree[rt].col;
    push_down(rt);
    int mid = (tree[rt].l+tree[rt].r)>>1;
    if (pos<=mid) return ask(rt<<1, pos);
    else return ask(rt<<1|1, pos);
}
int k;
int main(void) {
    int T; cin >> T;
    while(T--) {
        cin >> n; 
        printf("Case #%d:\n", ++k);
        build(1, 1, n);
        for (int i = 0, a, b; i<n-1; ++i) {
            scanf("%d%d", &a, &b);
            e[b].push_back(a); ++in[a];
        }
        int rt;
        for (int i = 1; i<=n; ++i)
            if (!in[i]) rt = i;
        tot = 0; dfs(rt, -1); 
        cin >> m;
        while(m--) {
            char ch[3]; scanf("%s", ch);
            if (ch[0]=='C') {
                int pos; scanf("%d", &pos);
                printf("%d\n", ask(1, num[pos]));
            }
            else {
                int x, y; scanf("%d%d", &x, &y);
                update(1, num[x], num[last[x]], y);
            }
        }
        for (int i = 1; i<=n; ++i) e[i].clear(), in[i] = 0;
    }
    return 0;
}
posted @ 2020-11-01 10:16  shuitiangong  阅读(102)  评论(0编辑  收藏  举报