Codeforces343D(SummerTrainingDay06-F dfs序+线段树)
D. Water Tree
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:
- Fill vertex v with water. Then v and all its children are filled with water.
- Empty vertex v. Then v and all its ancestors are emptied.
- 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 ai, bi (1 ≤ ai, bi ≤ n, ai ≠ 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 就可以了——因为这样就包含了所有的操作信息。这种观点下,再看这三种操作。
- u 点以及 u 点的所有子孙都赋值为 1:这个时候应该先看一看子孙有没有 0,如果有 0,那么说明 u 的祖先都是应该是 0 但是还没表现出来。所以我们把 u 的父亲标记成 0。这之后,我们再把所有的子孙赋值成 1。
- u 点以及 u 点的所有祖先都赋值为 0:u 标记成 0;
- 查询一个点 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序+线段树)的更多相关文章
- F - Change FZU - 2277 (DFS序+线段树)
题目链接: F - Change FZU - 2277 题目大意: 题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作 (1) 1 v k x : a[v] += x, a[v ' ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树
题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...
- BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树
题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...
- HDU.5692 Snacks ( DFS序 线段树维护最大值 )
HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- 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 ...
- 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)
P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...
- 【cf343】D. Water Tree(dfs序+线段树)
传送门 题意: 给出一个以\(1\)为根的有根树,起始每个结点都为\(0\),现在有三种操作: 1.将\(v\)及\(v\)的子树都置为\(1\): 2.将\(v\)及其所有的祖先都置为\(0\): ...
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
随机推荐
- 小猴打架(luogu4430)(数论+生成树计数)
一开始森林里面有\(N\)只互不相识的小猴子,它们经常打架,但打架的双方都必须不是好朋友.每次打完架后,打架的双方以及它们的好朋友就会互相认识,成为好朋友.经过\(N-1\)次打架之后,整个森林的小猴 ...
- Windows下Mongodb安装及配置
安装文件:MongoDB-win32-x86_64-2008plus-ssl-3.2.6-signed.msi 电脑配置:win7 64位 mongodb的安装很简单,设置好安装路径后,一直Next直 ...
- [Leetcode]315.计算右侧小于当前元素的个数 (6种方法)
链接 给定一个整数数组 nums,按要求返回一个新数组 counts.数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量. 示例: 输 ...
- oracle数据库迁移相关
常见的实现方式: rman exp/imp expdp/impdp DG OGG 主要是看停机时间了,方法很多,数据量小,就导出,如果时间要求很高,那可以采取dg或ogg或类似的技术.减低downt ...
- 课程一(Neural Networks and Deep Learning),第四周(Deep Neural Networks)—— 1.Practice Questions: Key concepts on Deep Neural Networks
[解释] [解释] 比如算法中的learing rateα(学习率).iterations(梯度下降法循环的数量).L(隐藏层数目).n[l] (隐藏层单元数目).choice of activati ...
- (转)Python自动化运维之13、异常处理及反射(__import__,getattr,hasattr,setattr)
原文:http://www.cnblogs.com/xiaozhiqi/p/5778856.html https://blog.csdn.net/zong596568821xp/article/det ...
- python应用
GUI(图形用户界面) python是可以创建GUI的,使用第三方库一般是Tk.wxWidgets.Qt.GTK. 而python自带的是支持Tk的Tkinter,我们这里就来用Tkinter来实现G ...
- 二:理解ASP.NET的运行机制(例:基于HttpHandler的URL重写)
url重写就是把一些类似article.aspx?id=28的路径重写成 article/28/这样的路径 当用户访问article/28/的时候我们通过asp.net把这个请求重定向到article ...
- springcloud~演化的微服务架构
微服务 将整体功能按着模块划分成多个独立的单元,这些单元可以独立部署,它们之前通过轻量级的web api方式进行通讯,对于微服务框架来说,最流行的就是springcloud和Service Fabri ...
- 最常用的两种C++序列化方案的使用心得(protobuf和boost serialization)
导读 1. 什么是序列化? 2. 为什么要序列化?好处在哪里? 3. C++对象序列化的四种方法 4. 最常用的两种序列化方案使用心得 正文 1. 什么是序列化? 程序员在编写应用程序的时候往往需要将 ...