博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces 343D 线段树
阅读量:5162 次
发布时间:2019-06-13

本文共 2782 字,大约阅读时间需要 9 分钟。

题意:给你一颗以点1为根的数,有两种操作,一种是把x及其子树的所有点都灌满水,一种是把x及其所有祖先都放空水,一种是询问,问某个点里有没有水?

思路:看网上大多数是树剖,但实际上5e5的数据树剖还是有点慌的。。。我只用了线段树。我们发现,只要一个点被清空之后,如果没有灌水,那么这个点将一直是空的。同理,如果这个点被灌满水后一直不是空的,那么它将一直是满的,所以,这个点的状态实际取决于离查询时间最近的是放水还是灌水。我们可以用线段树来维护这个,我们首先来维护灌水时间,这个在dfs序后用线段树的区间操作,很好完成。那么放水呢?我们换个思维,清空这个点及其祖先,反过来说,如果这个点被清空了,那么一定是它的子树中的某个点被清空了,所以我们可以用线段树查询它被清空的最晚时间,与之前的操作比较,如果清空操作较晚,那么这个点就是空的,否则就是满的。

代码:

#include 
#define LL long long#define INF 0x3f3f3f3f#define db double#define pii pair
#define ls (x << 1)#define rs ((x << 1) | 1)using namespace std;const int maxn = 500010;int a[maxn];int dfn[maxn], tot, sz[maxn];vector
G[maxn];struct node { int add, del; int lz;};node tr[maxn * 4];void add(int x, int y) { G[x].push_back(y); G[y].push_back(x);}void pushup(int x) { tr[x].del = max(tr[ls].del, tr[rs].del);}void maintain(int x, int y) { tr[x].add = y; tr[x].lz = y;}void pushdown(int x) { if(tr[x].lz != -1) { maintain(ls, tr[x].lz); maintain(rs, tr[x].lz); tr[x].lz = -1; }}void build(int x, int l, int r) { if(l == r) { tr[x].lz = -1; return; } int mid = (l + r) >> 1; build(ls, l, mid); build(rs, mid + 1, r); pushup(x);}void add1(int x, int l, int r, int ql ,int qr, int val) { if(l >= ql && r <= qr) { maintain(x, val); return; } pushdown(x); int mid = (l + r) >> 1; if(ql <= mid) add1(ls, l, mid, ql, qr, val); if(qr > mid) add1(rs, mid + 1, r, ql, qr, val); pushup(x);}void add2(int x, int l, int r, int pos, int val) { if(l == r) { tr[x].del = val; return; } pushdown(x); int mid = (l + r) >> 1; if(pos <= mid) add2(ls, l, mid, pos, val); else add2(rs, mid + 1, r, pos, val); pushup(x);}int query1(int x, int l, int r, int pos) { if(l == r) return tr[x].add; pushdown(x); int mid = (l + r) >> 1; if(pos <= mid) return query1(ls, l, mid, pos); else return query1(rs, mid + 1, r, pos);}int query2(int x, int l, int r, int ql, int qr) { if(l >= ql && r <= qr) return tr[x].del; pushdown(x); int mid = (l + r) >> 1; int ans = 0; if(ql <= mid) ans = max(ans, query2(ls, l, mid, ql, qr)); if(qr > mid) ans = max(ans, query2(rs, mid + 1, r, ql, qr)); return ans;} void dfs(int x, int fa) { dfn[x] = ++tot; sz[x] = 1; for (auto y : G[x]) { if(y == fa) continue; dfs(y, x); sz[x] += sz[y]; }}int main() { int n, m, x, y; scanf("%d", &n); for (int i = 1; i < n; i++) { scanf("%d%d", &x, &y); add(x, y); } dfs(1, -1); build(1, 1, n); scanf("%d", &m); for(int i = 1; i <= m; i++) { scanf("%d%d", &x, &y); if(x == 1) { add1(1, 1, n, dfn[y], dfn[y] + sz[y] - 1, i); } else if(x == 2) { add2(1, 1, n, dfn[y], i); } else { int tmp1 = query1(1, 1, n, dfn[y]), tmp2 = query2(1, 1, n, dfn[y], dfn[y] + sz[y] - 1); if(tmp1 <= tmp2) printf("0\n"); else printf("1\n"); } }}

  

转载于:https://www.cnblogs.com/pkgunboat/p/10952821.html

你可能感兴趣的文章
socket.io笔记一
查看>>
SQL 语句
查看>>
工作反思
查看>>
pip安装加速
查看>>
运维人员需要产品观
查看>>
shell脚本传参
查看>>
java输入分数显示等级
查看>>
MySQL备份之【mydumper 学习】
查看>>
CentOS 下 maven 安装
查看>>
质量保障
查看>>
mac 火狐 下载 任何文件都是失败
查看>>
Run Shell Commands in Python
查看>>
数组与泛型(2)
查看>>
20145322 Exp5 Adobe阅读器漏洞攻击
查看>>
使用System.out.print/prilntln() 输出时存在的问题
查看>>
angular-messages.js信息验证的使用
查看>>
HDU ACM 2844 Coins (多重背包)----------------01背包,完全背包,多重背包模板
查看>>
Docker 命令大全
查看>>
Linux c 根据socket套接字获取当前监听的端口
查看>>
scala 16 包
查看>>