CF343D Water Tree
$ \color{#0066ff}{ 题目描述 }$
疯狂科学家Mike培养了一颗有根树,由n个节点组成。每个节点是一个要么装满水要么为空的贮水容器. 树的节点用1~n编号,其中根节点为1.对于每个节点的容器,其子节点的容器均在这一容器下方,并且每个节点都由一根可以向下流水的管道与其子节点连接. Mike想要对这棵树做以下操作:
将节点v注满水. 这样v和其子节点都会充满水.
将节点v置空. 这样v及其祖先节点(从v到根节点的路径)都会被置空.
查询当前节点v是否充满水.
初始时,所有节点都为空. Mike已经制定好了他的操作顺序. 在对树进行实验前,他决定先模拟一下操作. 请你帮助Mike得出他操作后的结果.
\(\color{#0066ff}{输入格式}\)
第一行为一个整数n(1<=n<=500000),为树的节点数;
下面的n-1行为两个空格隔开的整数ai,bi(1<=ai, bi<=n),为树的边;
下一行为一个整数q(1<=q<=500000),为操作数;接下来q行,两个空格隔开的整数ci(1<=ci<=3),vi(1<=vi<=n),其中ci为操作类型(已给出),vi为被操作的节点.
这意味着给出的图为一棵树.
\(\color{#0066ff}{输出格式}\)
对于每一次操作3,如果节点v充满水,单独输出一行1,如果节点v为空,单独输出一行0. 按照操作输入的顺序输出.
\(\color{#0066ff}{输入样例}\)
5
1 2
5 1
2 3
4 2
12
1 1
2 3
3 1
3 2
3 3
3 4
1 2
2 4
3 1
3 3
3 4
3 5
\(\color{#0066ff}{输出样例}\)
0
0
0
1
0
1
0
1
\(\color{#0066ff}{数据范围与提示}\)
none
\(\color{#0066ff}{题解}\)
一个是树链操作,一个是子树操作,直接树剖,线段树甚至不用upd,因为不用维护任何东西。。
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 5e5 + 10;
struct Tree {
protected:
struct node {
node *ch[2];
int l, r, val, tag;
node(int l = 0, int r = 0, int val = 0, int tag = -1): l(l), r(r), val(val), tag(tag) {}
void trn(int v) { tag = val = v; }
void dwn() {
if(!(~tag)) return;
ch[0]->trn(tag), ch[1]->trn(tag);
tag = -1;
}
int mid() { return (l + r) >> 1; }
}*root;
void build(node *&o, int l, int r) {
o = new node(l, r, 0, -1);
if(l == r) return;
int mid = (l + r) >> 1;
build(o->ch[0], l, mid);
build(o->ch[1], mid + 1, r);
}
void lazy(node *o, int l, int r, int val) {
if(l <= o->l && o->r <= r) return o->trn(val);
o->dwn();
if(l <= o->mid()) lazy(o->ch[0], l, r, val);
if(r > o->mid()) lazy(o->ch[1], l, r, val);
}
int query(node *o, int pos) {
if(o->l == o->r) return o->val;
o->dwn();
if(pos <= o->mid()) return query(o->ch[0], pos);
else return query(o->ch[1], pos);
}
public:
void lazy(int l, int r, int val) { lazy(root, l, r, val); }
int query(int pos) { return query(root, pos); }
void build(int l, int r) { build(root, l, r); }
}s;
struct node {
int to;
node *nxt;
node(int to = 0, node *nxt = NULL): to(to), nxt(nxt) {}
};
node *head[maxn];
int dep[maxn], siz[maxn], top[maxn], fa[maxn];
int dfn[maxn], nfd[maxn], son[maxn], cnt;
void add(int from, int to) {
head[from] = new node(to, head[from]);
}
void dfs1(int x, int f) {
dep[x] = dep[fa[x] = f] + (siz[x] = 1);
for(node *i = head[x]; i; i = i->nxt) {
if(i->to == f) continue;
dfs1(i->to, x);
siz[x] += siz[i->to];
if(!son[x] || siz[i->to] > siz[son[x]]) son[x] = i->to;
}
}
void dfs2(int x, int t) {
top[nfd[dfn[x] = ++cnt] = x] = t;
if(son[x]) dfs2(son[x], t);
for(node *i = head[x]; i; i = i->nxt)
if(!dfn[i->to])
dfs2(i->to, i->to);
}
void up(int x) {
for(; top[x]; x = fa[top[x]]) s.lazy(dfn[top[x]], dfn[x], 0);
}
int main() {
int n = in();
int x, y;
for(int i = 1; i < n; i++) x = in(), y = in(), add(x, y), add(y, x);
dfs1(1, 0), dfs2(1, 1), s.build(1, n);
for(int T = in(); T --> 0;) {
x = in(), y = in();
if(x == 1) s.lazy(dfn[y], dfn[y] + siz[y] - 1, 1);
if(x == 2) up(y);
if(x == 3) printf("%d\n", s.query(dfn[y]));
}
return 0;
}
----olinr