zoukankan      html  css  js  c++  java
  • CF343D Water Tree

    $ color{#0066ff}{ 题目描述 }$

    疯狂科学家Mike培养了一颗有根树,由n个节点组成。每个节点是一个要么装满水要么为空的贮水容器. 树的节点用1~n编号,其中根节点为1.对于每个节点的容器,其子节点的容器均在这一容器下方,并且每个节点都由一根可以向下流水的管道与其子节点连接. Mike想要对这棵树做以下操作:

    将节点v注满水. 这样v和其子节点都会充满水.
    将节点v置空. 这样v及其祖先节点(从v到根节点的路径)都会被置空.
    查询当前节点v是否充满水.
    

    初始时,所有节点都为空. Mike已经制定好了他的操作顺序. 在对树进行实验前,他决定先模拟一下操作. 请你帮助Mike得出他操作后的结果.

    (color{#0066ff}{输入格式})

    第一行为一个整数n(1<=n<=500000),为树的节点数;
    下面的n-1行为两个空格隔开的整数ai,bi(1<=ai, bi<=n),为树的边;
    下一行为一个整数q(1<=q<=500000),为操作数;接下来q行,两个空格隔开的整数ci(1<=ci<=3),vi(1<=vi<=n),其中ci为操作类型(已给出),vi为被操作的节点.
    这意味着给出的图为一棵树.

    (color{#0066ff}{输出格式})

    对于每一次操作3,如果节点v充满水,单独输出一行1,如果节点v为空,单独输出一行0. 按照操作输入的顺序输出.

    (color{#0066ff}{输入样例})

    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
    

    (color{#0066ff}{输出样例})

    0
    0
    0
    1
    0
    1
    0
    1
    

    (color{#0066ff}{数据范围与提示})

    none

    (color{#0066ff}{题解})

    一个是树链操作,一个是子树操作,直接树剖,线段树甚至不用upd,因为不用维护任何东西。。

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int maxn = 5e5 + 10;
    struct Tree {
    protected:
    	struct node {
    		node *ch[2];
    		int l, r, val, tag;
    		node(int l = 0, int r = 0, int val = 0, int tag = -1): l(l), r(r), val(val), tag(tag) {}
    		void trn(int v) { tag = val = v; }
    		void dwn() {
    			if(!(~tag)) return;
    			ch[0]->trn(tag), ch[1]->trn(tag);
    			tag = -1;
    		}
    		int mid() { return (l + r) >> 1; }
    	}*root;
    	void build(node *&o, int l, int r) {
    		o = new node(l, r, 0, -1);
    		if(l == r) return;
    		int mid = (l + r) >> 1;
    		build(o->ch[0], l, mid);
    		build(o->ch[1], mid + 1, r);
    	}
    	void lazy(node *o, int l, int r, int val) {
    		if(l <= o->l && o->r <= r) return o->trn(val);
    		o->dwn();
    		if(l <= o->mid()) lazy(o->ch[0], l, r, val);
    		if(r > o->mid()) lazy(o->ch[1], l, r, val);
    	}
    	int query(node *o, int pos) {
    		if(o->l == o->r) return o->val;
    		o->dwn();
    		if(pos <= o->mid()) return query(o->ch[0], pos);
    		else return query(o->ch[1], pos);
    	}
    public:
    	void lazy(int l, int r, int val) { lazy(root, l, r, val); }
    	int query(int pos) { return query(root, pos); }
    	void build(int l, int r) { build(root, l, r); }
    }s;
    struct node {
    	int to;
    	node *nxt;
    	node(int to = 0, node *nxt = NULL): to(to), nxt(nxt) {}
    };
    node *head[maxn];
    int dep[maxn], siz[maxn], top[maxn], fa[maxn];
    int dfn[maxn], nfd[maxn], son[maxn], cnt;
    void add(int from, int to) {
    	head[from] = new node(to, head[from]); 
    }
    void dfs1(int x, int f) {
    	dep[x] = dep[fa[x] = f] + (siz[x] = 1);
    	for(node *i = head[x]; i; i = i->nxt) {
    		if(i->to == f) continue;
    		dfs1(i->to, x);
    		siz[x] += siz[i->to];
    		if(!son[x] || siz[i->to] > siz[son[x]]) son[x] = i->to;
    	}
    }
    void dfs2(int x, int t) {
    	top[nfd[dfn[x] = ++cnt] = x] = t;
    	if(son[x]) dfs2(son[x], t);
    	for(node *i = head[x]; i; i = i->nxt) 
    		if(!dfn[i->to]) 
    			dfs2(i->to, i->to);
    }
    void up(int x) {
    	for(; top[x]; x = fa[top[x]]) s.lazy(dfn[top[x]], dfn[x], 0);
    }
    int main() {
    	int n = in();
    	int x, y;
    	for(int i = 1; i < n; i++) x = in(), y = in(), add(x, y), add(y, x);
    	dfs1(1, 0), dfs2(1, 1), s.build(1, n);
    	for(int T = in(); T --> 0;) {
    		x = in(), y = in();
    		if(x == 1) s.lazy(dfn[y], dfn[y] + siz[y] - 1, 1);
    		if(x == 2) up(y);
    		if(x == 3) printf("%d
    ", s.query(dfn[y]));
    	}
    	return 0;
    
    }
    
    
  • 相关阅读:
    ios开发ios9新特性关键字学习:泛型,逆变,协变,__kindof
    ios开发Base64编码以及加密相关学习
    ios开发网络学习AFN三:AFN的序列化
    iOS开发AFN使用二:AFN文件下载与文件上传
    Android开发:《Gradle Recipes for Android》阅读笔记(翻译)2.4——更新新版本的Gradle
    Android开发:《Gradle Recipes for Android》阅读笔记(翻译)2.3——用Eclipse ADT导出App
    Android开发:《Gradle Recipes for Android》阅读笔记(翻译)2.2——将Eclipse开发的项目导入到AndroidStudio
    Android开发:《Gradle Recipes for Android》阅读笔记(翻译)2.1——设置项目参数
    Android开发:《Gradle Recipes for Android》阅读笔记1.7——仓库配置
    Android开发:《Gradle Recipes for Android》阅读笔记1.6——使用android studio添加依赖
  • 原文地址:https://www.cnblogs.com/olinr/p/10460932.html
Copyright © 2011-2022 走看看