题目链接
https://codeforces.com/contest/343/problem/D
题意
给出一棵以 (1) 为根节点的 (n) 个节点的有根树。每个点有一个权值,初始为 (0)。
(m) 次操作。操作有 (3) 种:
1.将点 (u) 和其子树上的所有节点的权值改为 (1)。
2.将点 (u) 到 (1) 的路径上的所有节点的权值改为 (0)。
3.询问点 (u) 的权值。
思路
利用DFS序建树, 对于操作1就是简单的区间更新。
操作2在DFS序上是离散的, 不能直接暴力更新,
换个思路,我们可以只更新这个点。
容易想到每次1操作填满子树, 假如一个点当前为1,那么它的所有子树必定都是1, 如果子树某个节点的权值为0, 那么2操作必定把这个节点的祖先都更新了。
那么操作三只需要查询该点以及其子树是否都为1即可。
注意操作1时,若u的子树中有0,必须把u的父亲更新成0。
AC代码
#include<bits/stdc++.h>
#define ls rt << 1
#define rs rt << 1 | 1
#define lson l , mid , rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define lr2 (l + r) >> 1
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 50;
int sum[maxn << 2], lazy[maxn << 2];
int a[maxn];
void push_up(int rt){
sum[rt] = sum[ls] & sum[rs];
}
void push_down(int rt){
if(lazy[rt]){
sum[ls] = 1;
sum[rs] = 1;
lazy[ls] = 1;
lazy[rs] = 1;
lazy[rt] = 0;
}
}
void update(int a, int b, int l, int r, int rt){
if(a <= l && b >= r){
lazy[rt] = 1;
sum[rt] = 1;
return;
}
push_down(rt);
int mid = lr2;
if(a <= mid) update(a, b, lson);
if(b > mid) update(a, b, rson);
push_up(rt);
}
void insert(int pos, int val, int l, int r, int rt){
if(l == r){
lazy[rt] = 0;
sum[rt] = val;
return;
}
push_down(rt);
int mid = lr2;
if(pos <= mid) insert(pos, val, lson);
else insert(pos, val, rson);
push_up(rt);
}
int query(int a, int b, int l, int r, int rt){
if(a <= l && b >= r){
return sum[rt];
}
int mid = lr2;
push_down(rt);
int ans = 1;
if(a <= mid) ans &= query(a, b, lson);
if(b > mid) ans &= query(a, b, rson);
push_up(rt);
return ans;
}
int cnt, n;
vector<int> G[maxn];
int L[maxn], R[maxn];
int far[maxn];
void dfs(int v, int fa){
far[v] = fa;
L[v] = ++cnt;
for(auto u : G[v]){
if(u != fa){
dfs(u, v);
}
}
R[v] = cnt;
}
int main()
{
std::ios::sync_with_stdio(false);
cin >> n;
for(int i = 2;i <= n;i++){
int x, y;cin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1, -1);
int q;
cin >> q;
while(q--){
int op, x;
cin >> op >> x;
if(op == 1){
if(!query(L[x], R[x], 1, n , 1)) insert(L[far[x]], 0, 1, n , 1);
update(L[x], R[x], 1, n , 1);
}
else if(op == 2) insert(L[x], 0, 1, n , 1);
else {
cout << query(L[x], R[x], 1, n, 1) << endl;
}
}
return 0;
}