CodeForces 343D 线段树维护dfs序
给定一棵树,初始时树为空
操作1,往某个结点注水,那么该结点的子树都注满了水
操作2,将某个结点的水放空,那么该结点的父亲的水也就放空了
操作3,询问某个点是否有水
我们将树进行dfs, 生成in[u], 访问结点u的时间戳,out[u],离开结点u的时间戳
每个结点的in值对应在线段树中的区间的一点
那么对于操作1, 只要将区间[in[u],out[u]] 的值都改为1, 但是如果区间[in[u],out[u]] 原先存在为0的点,那么父区间肯定是空的,这个操作不能
改变父区间的状态,所以需要将in[fa[u]]置为0,
对于操作2,只要将in[u] 置为0就行了
对于操作3,只要区间[in[u],out[u]]内不存在为0的点,那么点u就是有水的
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
const int INF = <<;
/*
我们对树进行dfs,求出dfs序列 in[] 和out[] 用线段树维护这个序列
操作1就是将[in[b],out[b]]区间内的点都变为1 , 如果区间内存在0,那么要将b的父结点更新为0,因为虽然更新了[in[b],out[b]],但是祖先不会变
操作2就是将点in[b]置为0
操作3就是看区间[in[b],out[b]] 所以不仅可以将树进行树链剖分,然后用线段树维护
还可以用线段树维护树的dfs序列
*/
const int N = + ;
int in[N], out[N], num, fa[N];
int tree[N * ], laze[N * ];
vector<int> g[N];
void dfs(int u)
{
in[u] = ++num;
for (int i = ; i < g[u].size(); ++i)
{
int v = g[u][i];
if (v != fa[u])
{
fa[v] = u;
dfs(v);
}
}
out[u] = num;
}
void pushDown(int rt)
{
if (laze[rt]==)
{
tree[rt << ] = tree[rt << | ] = laze[rt << ] = laze[rt << | ] = ;
laze[rt] = ;
}
}
void pushUp(int rt)
{
if (tree[rt << ] == || tree[rt << | ] == )
tree[rt] = ;
else
tree[rt] = ;
}
bool flag = false;
void update(int l, int r, int rt, int L, int R, int val)
{
pushDown(rt);
if (L<=l && R>=r)
{
if (tree[rt] == )
flag = true;
tree[rt] = val;
laze[rt] = val;
return;
}
int mid = (l + r) >> ;
if (L <= mid)
update(l, mid, rt << , L, R, val);
if (R > mid)
update(mid + , r, rt << | , L, R, val);
pushUp(rt);
} void query(int l, int r, int rt, int L, int R)
{
pushDown(rt);
if (L<=l && R>=r)
{
//区间内有一个是0,那么所访问的点(根)就是0
if (tree[rt] == )
flag = false;
return;
}
int mid = (l + r) >> ;
if (L <= mid)
query(l, mid, rt << , L, R);
if (R > mid)
query(mid + , r, rt << | , L, R);
pushUp(rt);
}
int main()
{
//freopen("d:/in.txt", "r", stdin);
int n, q, a, b,x, y;
scanf("%d", &n);
for (int i = ; i < n; ++i)
{
scanf("%d%d", &a, &b);
g[a].push_back(b);
g[b].push_back(a);
}
fa[] = ;
dfs();
scanf("%d", &q);
while (q--)
{
scanf("%d%d", &a, &b);
if (a == )
{
flag = false;
//将区间内的点都置为1
update(, n, , in[b], out[b],);
//如果区间内存在0的点,那么fa[b]肯定为空,
if (flag&&fa[b]!=)
{
update(, n, , in[fa[b]],in[fa[b]],);
}
}
else if (a == )
{
update(, n, , in[b],in[b],);
}
else
{
flag = true;
query(,n, , in[b], out[b]);
if (flag)
printf("1\n");
else
printf("0\n");
}
}
return ;
}
CodeForces 343D 线段树维护dfs序的更多相关文章
- CF877E Danil and a Part-time Job 线段树维护dfs序
\(\color{#0066ff}{题目描述}\) 有一棵 n 个点的树,根结点为 1 号点,每个点的权值都是 1 或 0 共有 m 次操作,操作分为两种 get 询问一个点 x 的子树里有多少个 1 ...
- P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA
\(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...
- bzoj 3779: 重组病毒【LCT+线段树维护dfs序】
%.8lf会WA!!%.8lf会WA!!%.8lf会WA!!要%.10lf!! 和4817有点像,但是更复杂. 首先对于操作一"在编号为x的计算机中植入病毒的一个新变种,在植入一个新变种时, ...
- BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)
题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...
- 【HIHOCODER 1576】 子树中的最小权值(线段树维护DFS序)
描述 给定一棵N个节点的树,编号1~N.其中1号节点是根,并且第i个节点的权值是Vi. 针对这棵树,小Hi会询问小Ho一系列问题.每次小Hi会指定一个节点x,询问小Ho以x为根的子树中,最小的权值是多 ...
- Codeforces 343D Water Tree(DFS序 + 线段树)
题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...
- codeforces 877 E. Danil and a Part-time Job(线段树(dfs序))
题目链接:http://codeforces.com/contest/877/problem/E 题解:显然一看就感觉要么树链剖分要么线段树+dfs序,题目要求的操作显然用线段树+dfs序就可以实现. ...
- 2018.11.01 NOIP训练 图论(线段树+倍增+dfs序)
传送门 一道挺妙的题. 对于询问点(u,v),如右图所示,我们可以发现存在一个点m在u->v的路径中,m子树的点到u是最近的,m子树外到v是最近的.其中dis(u,m)=(dis(u,v)-1) ...
- Codeforces 343D 线段树
题意:给你一颗以点1为根的数,有两种操作,一种是把x及其子树的所有点都灌满水,一种是把x及其所有祖先都放空水,一种是询问,问某个点里有没有水? 思路:看网上大多数是树剖,但实际上5e5的数据树剖还是有 ...
随机推荐
- freemarker的TemplateExceptionHandler使用
系统使用freemarker作为页面展示层,为了解决系统统一异常的问题.于是配置了struts2的统一异常解决的方法(这个网上资料非常多,大家能够查看),但是发现freemarker出现异常后,str ...
- 图解UML类与类之间的六中关系
大话设计模式上的一个图,我用EA画出来的: UML中的6大关系相关英文及音标: 依赖关系 dependency [di'pendənsi] 关联关系 association [ə,səuʃi' ...
- 与众不同 windows phone (20) - Device(设备)之位置服务(GPS 定位), FM 收音机, 麦克风, 震动器
原文:与众不同 windows phone (20) - Device(设备)之位置服务(GPS 定位), FM 收音机, 麦克风, 震动器 [索引页][源码下载] 与众不同 windows phon ...
- 4.锁--无锁编程以及CAS
无锁编程以及CAS 无锁编程 / lock-free / 非堵塞同步 无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被堵塞的情况下实现变量的同步,所以也叫非堵塞同步(Non-b ...
- PyMOTW: heapq¶
PyMOTW: heapq — PyMOTW Document v1.6 documentation PyMOTW: heapq¶ 模块: heapq 目的: 就地堆排序算法 python版本:New ...
- 飘逸的python - yield简明教程
发现还有非常多人对yield不理解,云里雾里,于是试着用文字表述. 仅仅要函数含有yield语句,它就返回一个生成器.所以我们与其把其看成函数定义,不如看作是生成器定义.函数用return返回,而生成 ...
- Cocos2d-x内存管理解说在ios开发中
使用过 Cocos2d-x 都知道,其中有一套自己实现的内存管理机制,不同于一般 C++ 的编写常规,而在使用前,了解其原理是有必要的,网上已经有很多对内部实现详细解说的文章.而对于使用者而言,并不需 ...
- oracle 之 内存—鞭辟近里(二)
overview of the pga pga是在操作系统的进程或是线程特定的一块内存区域,它不是共享的.因为pga是进程指定的,因此它不会在sga中分配. pga是一个内存堆,其中包含了被专用服务器 ...
- VSTO之旅系列(四):创建Word解决方案
原文:VSTO之旅系列(四):创建Word解决方案 本专题概要 引言 Word对象模型 创建Word外接程序 小结 一.引言 在上一个专题中主要为大家介绍如何自定义我们的Excel 界面的,然而在这个 ...
- oracle instr函数
语法:instr( fatherstr, sonstr [, start_position [, matchtimes ] ] ) fatherstr:父字符串.要在此字符串中查找子字符串的位置. s ...