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;
}