D. Water Tree

time limit per test:4 seconds
memory limit per test:256 megabytes
input:standard input
output:standard output

Mad scientist Mike has constructed a rooted tree, which consists of n vertices. Each vertex is a reservoir which can be either empty or filled with water.

The vertices of the tree are numbered from 1 to n with the root at vertex 1. For each vertex, the reservoirs of its children are located below the reservoir of this vertex, and the vertex is connected with each of the children by a pipe through which water can flow downwards.

Mike wants to do the following operations with the tree:

  1. Fill vertex v with water. Then v and all its children are filled with water.
  2. Empty vertex v. Then v and all its ancestors are emptied.
  3. Determine whether vertex v is filled with water at the moment.

Initially all vertices of the tree are empty.

Mike has already compiled a full list of operations that he wants to perform in order. Before experimenting with the tree Mike decided to run the list through a simulation. Help Mike determine what results will he get after performing all the operations.

Input

The first line of the input contains an integer n (1 ≤ n ≤ 500000) — the number of vertices in the tree. Each of the following n - 1 lines contains two space-separated numbers aibi (1 ≤ ai, bi ≤ nai ≠ bi) — the edges of the tree.

The next line contains a number q (1 ≤ q ≤ 500000) — the number of operations to perform. Each of the following q lines contains two space-separated numbers ci (1 ≤ ci ≤ 3), vi (1 ≤ vi ≤ n), where ci is the operation type (according to the numbering given in the statement), and vi is the vertex on which the operation is performed.

It is guaranteed that the given graph is a tree.

Output

For each type 3 operation print 1 on a separate line if the vertex is full, and 0 if the vertex is empty. Print the answers to queries in the order in which the queries are given in the input.

Examples

input

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

output

0
0
0
1
0
1
0
1

这颗树具有一个重要的特性,当一个点是 0 的时候,这个点的全部祖先一定都是 0;一点是 1,这个点的全部子孙都是 1。

利用这个性质,如果我们要把一个节点以及他的祖先都变成 0,我们只要把这个点标记成 0 就可以了——因为这样就包含了所有的操作信息。这种观点下,再看这三种操作。

  1. u 点以及 u 点的所有子孙都赋值为 1:这个时候应该先看一看子孙有没有 0,如果有 0,那么说明 u 的祖先都是应该是 0 但是还没表现出来。所以我们把 u 的父亲标记成 0。这之后,我们再把所有的子孙赋值成 1。
  2. u 点以及 u 点的所有祖先都赋值为 0:u 标记成 0;
  3. 查询一个点 u 的值:u 以及 u 的所以子孙的标记都不是 0,u 才真正的是 1。

这样一看,好开心,这三种操作都变成了树上的单点修改或者是一整个子树的整体修改。这个解决起来就很套路了,我们把树按照 dfs 序展开,就变成了线段树连续区间修改的问题。

 //2017-09-01
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lson (id<<1)
#define rson ((id<<1)|1) using namespace std; const int N = ; int head[N], tot;
struct Edge{
int to, next;
}edge[N<<]; void init(){
tot = ;
memset(head, -, sizeof(head));
} void add_edge(int u, int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} int in[N], out[N], fa[N], cnt;
void dfs(int u, int father){
in[u] = ++cnt;
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;
if(v != father){
fa[v] = u;
dfs(v, u);
}
}
out[u] = cnt;
} bool flag;
struct Node{
int l, r, value, lazy;
}tree[N<<]; void build(int id, int l, int r){
tree[id].l = l;
tree[id].r = r;
tree[id].value = ;
tree[id].lazy = ;
if(l == r)return;
int mid = (tree[id].l+tree[id].r)>>;
build(lson, l, mid);
build(rson, mid+, r);
} void push_up(int id){
if(tree[lson].value && tree[rson].value)tree[id].value = ;
else tree[id].value = ;
} void push_down(int id){
if(tree[id].lazy){
tree[lson].value = tree[rson].value = tree[id].lazy;
tree[lson].lazy = tree[rson].lazy = tree[id].lazy;
tree[id].lazy = ;
}
} void update(int id, int l, int r, int op){
if(l == )return;
if(l <= tree[id].l && tree[id].r <= r){
if(tree[id].value == )flag = ;
tree[id].value = op;
if(op == )tree[id].lazy = op;
return;
}
push_down(id);
int mid = (tree[id].l+tree[id].r)>>;
if(l <= mid)update(lson, l, r, op);
if(r > mid)update(rson, l, r, op);
push_up(id);
} void query(int id, int l, int r){
if(l <= tree[id].l && tree[id].r <= r){
if(tree[id].value == )flag = ;
return;
}
push_down(id);
int mid = (tree[id].l+tree[id].r)>>;
if(l <= mid)query(lson, l, r);
if(r > mid)query(rson, l, r);
} int n, q; int main()
{
//freopen("inputF.txt", "r", stdin);
while(scanf("%d", &n) != EOF){
init();
int u, v;
for(int i = ; i < n-; i++){
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
fa[] = ;
cnt = ;
dfs(, );
build(, , n);
scanf("%d", &q);
while(q--){
scanf("%d%d", &u, &v);
if(u == ){
flag = ;
update(, in[v], out[v], );
if(!flag)update(, in[fa[v]], in[fa[v]], );
}else if(u == ){
update(, in[v], in[v], );
}else{
flag = ;
query(, in[v], out[v]);
if(flag)printf("1\n");
else printf("0\n");
}
}
} return ;
}

Codeforces343D(SummerTrainingDay06-F dfs序+线段树)的更多相关文章

  1. F - Change FZU - 2277 (DFS序+线段树)

    题目链接: F - Change FZU - 2277 题目大意: 题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作 (1) 1 v k x : a[v] += x, a[v ' ...

  2. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  3. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

  4. BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树

    题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...

  5. HDU.5692 Snacks ( DFS序 线段树维护最大值 )

    HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...

  6. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  7. CodeForces 877E Danil and a Part-time Job(dfs序+线段树)

    Danil decided to earn some money, so he had found a part-time job. The interview have went well, so ...

  8. 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)

    P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...

  9. 【cf343】D. Water Tree(dfs序+线段树)

    传送门 题意: 给出一个以\(1\)为根的有根树,起始每个结点都为\(0\),现在有三种操作: 1.将\(v\)及\(v\)的子树都置为\(1\): 2.将\(v\)及其所有的祖先都置为\(0\): ...

  10. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

随机推荐

  1. pringboot+mybatis+redis+cookie单点登录

    一.基本思路 单点sso用于多系统分布式,当多个系统分布式部署后,当然需要统一的登录接口.sso应运而生. 可以想见,单点应该是提供一个服务给其他系统,当其他系统需要验证登录状态的时候,调用服务,就可 ...

  2. 【learning】 扩展欧几里得算法(扩展gcd)和乘法逆元

    有这样的问题: 给你两个整数数$(a,b)$,问你整数$x$和$y$分别取多少时,有$ax+by=gcd(x,y)$,其中$gcd(x,y)$表示$x$和$y$的最大公约数. 数据范围$a,b≤10^ ...

  3. Python Web框架 tornado 异步原理

    Python Web框架 tornado 异步原理 参考:http://www.jb51.net/article/64747.htm 待整理

  4. Java8-函数复合用法

    JDK8自带的函数式接口Function有两个默认方法andThen和compose,它们都返回Function的一个实例,可以用这两个方法把Function接口所代表的的Lambda表达式复合起来. ...

  5. JavaScript与CSS相对路径引用的差异

    转自:http://blog.csdn.net/luohuidong01/article/details/74938652 JS跟CSS相对路径引用的差异在于他们的参考点不一样,下面举个例子说明一下. ...

  6. vue中修改Element ui样式不起作用

    公司做的一个后台系统,由于Elemen ui是响应式的,在小屏笔记本中,一行两列的表单会自动变成一行一列,这样就很不美观了,由于是后台系统,当时也没考虑适配问题. 老总 地表最强的电脑 运行了一下,当 ...

  7. win10上Tensorflow的安装教程

    这几天打算自己入门学习机器学习的内容,首先要安装Tensorflow. 自己捣鼓了几天才捣鼓出来.可能真的是比较笨orz 现在试试写一个教程,希望可以帮到迷路滴孩子们! 大体地说四步: 安装pytho ...

  8. Shell脚本 | 一键获取安卓应用活动名

    上篇文章提到,启动时间的计算需要用到应用启动页的活动名(Activity_Name). 如何获取活动名呢?通常有如下几种方式: 1.询问 Dev 同事 2.adb logcat ActivityMan ...

  9. 详解Java中的final关键字

    本文原文地址:https://jiang-hao.com/articles/2019/coding-java-final-keyword.html1 final 简介2 final关键字可用于多个场景 ...

  10. 通过DataTrigger绑定Tag属性值进行判断(.net 3.5的环境)

    如下,在UserControl中通过Tag传递不同的值,然后在Style中使用DataTrigger进行判断, <UserControl Style="{DynamicResource ...