zoukankan      html  css  js  c++  java
  • [洛谷P3979]遥远的国度

    题目大意:有一棵$n$个点的树,每个点有一个点权,有三种操作:

    1. $1;x:$把根变成$x$
    2. $2;u;v;x:$把路径$u->v$上的点权改为$x$
    3. $3;x:$询问以$x$为根的子树中最小的点权

    题解:树剖,发现换根操作比较困难,可以进行一波分类讨论(下面的$lca$以及子树都是在以$1$为根的情况下(其实任意一个固定的点均可)

    1. $root=x:$就是询问整棵树
    2. $lca(root,x) ot=x:$就是正常询问$x$的子树
    3. $lca(root,x)=x:$就是整棵树减去$root$所在的子树

    然后步骤三的减去$root$所在的子树中的找这棵子树可以用倍增来求

    卡点:步骤三中只查询了$x$的子树减去$root$子树

    C++ Code:

    #include <algorithm>
    #include <cstdio>
    #include <cctype>
    namespace std {
    	struct istream {
    #define M (1 << 24 | 3)
    		char buf[M], *ch = buf - 1;
    		inline istream() {
    #ifndef ONLINE_JUDGE
    			freopen("input.txt", "r", stdin);
    #endif
    			fread(buf, 1, M, stdin);
    		}
    		inline istream& operator >> (int &x) {
    			while (isspace(*++ch));
    			for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
    			return *this;
    		}
    #undef M
    	} cin;
    	struct ostream {
    #define M (1 << 24 | 3)
    		char buf[M], *ch = buf - 1;
    		inline ostream& operator << (int x) {
    			if (!x) {
    				*++ch = '0';
    				return *this;
    			}
    			static int S[20], *top; top = S;
    			while (x) {
    				*++top = x % 10 ^ 48;
    				x /= 10;
    			}
    			for (; top != S; --top) *++ch = *top;
    			return *this;
    		}
    		inline ostream& operator << (const char x) {*++ch = x; return *this;}
    		inline ~ostream() {
    #ifndef ONLINE_JUDGE
    			freopen("output.txt", "w", stdout);
    #endif
    			fwrite(buf, 1, ch - buf + 1, stdout);
    		}
    #undef M
    	} cout;
    }
    
    #define maxn 100010
    const int inf = 0x7fffffff;
    
    int head[maxn], cnt;
    struct Edge {
    	int to, nxt;
    } e[maxn << 1];
    inline void addedge(int a, int b) {
    	e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
    	e[++cnt] = (Edge) {a, head[b]}; head[b] = cnt;
    }
    
    int n, m;
    int w[maxn], W[maxn];
    namespace SgT {
    	int V[maxn << 2], tg[maxn << 2];
    	inline void pushdown(int rt) {
    		int &__tg = tg[rt];
    		V[rt << 1] = tg[rt << 1] = V[rt << 1 | 1] = tg[rt << 1 | 1] = __tg;
    		__tg = 0;
    	}
    
    	int L, R, num;
    	void build(int rt, int l, int r) {
    		if (l == r) {
    			V[rt] = W[l];
    			return ;
    		}
    		int mid = l + r >> 1;
    		build(rt << 1, l, mid);
    		build(rt << 1 | 1, mid + 1, r);
    		V[rt] = std::min(V[rt << 1], V[rt << 1 | 1]);
    	}
    	void __modify(int rt, int l, int r) {
    		if (L <= l && R >= r) {
    			V[rt] = tg[rt] = num;
    			return ;
    		}
    		int mid = l + r >> 1;
    		if (tg[rt]) pushdown(rt);
    		if (L <= mid) __modify(rt << 1, l, mid);
    		if (R > mid) __modify(rt << 1 | 1, mid + 1, r);
    		V[rt] = std::min(V[rt << 1], V[rt << 1 | 1]);
    	}
    	void modify(int __L, int __R, int __num) {
    		L = __L, R = __R, num = __num;
    		__modify(1, 1, n);
    	}
    
    	int ans;
    	void __query(int rt, int l, int r) {
    		if (L <= l && R >= r) {
    			ans = std::min(ans, V[rt]);
    			return ;
    		}
    		int mid = l + r >> 1;
    		if (tg[rt]) pushdown(rt);
    		if (L <= mid) __query(rt << 1, l, mid);
    		if (R > mid) __query(rt << 1 | 1, mid + 1, r);
    	}
    	int query(int __L, int __R) {
    		L = __L, R = __R;
    		ans = inf;
    		__query(1, 1, n);
    		return ans;
    	}
    }
    
    int root;
    int fa[maxn], sz[maxn], dfn[maxn], idx;
    int son[maxn], top[maxn], dep[maxn];
    
    namespace BZ {
    #define M 17
    	int fa[maxn][M + 1];
    	inline void init(int u) {
    		*fa[u] = ::fa[u];
    		for (int i = 1; i <= M; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
    	}
    	inline int get_son(int x, int y) {
    		for (int i = M; ~i; i--) if (dep[fa[x][i]] > dep[y]) x = fa[x][i];
    		return x;
    	}
    #undef M
    }
    using BZ::get_son;
    
    void dfs1(int u) {
    	BZ::init(u);
    	sz[u] = 1;
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (v != fa[u]) {
    			fa[v] = u;
    			dep[v] = dep[u] + 1;
    			dfs1(v);
    			sz[u] += sz[v];
    			if (!son[u] || sz[v] > sz[son[u]]) son[u] = v;
    		}
    	}
    }
    void dfs2(int u) {
    	dfn[u] = ++idx;
    	int v = son[u];
    	if (v) top[v] = top[u], dfs2(v);
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (v != fa[u] && v != son[u]) {
    			top[v] = v;
    			dfs2(v);
    		}
    	}
    }
    inline int LCA(int x, int y) {
    	if (x == y) return x;
    	while (top[x] != top[y]) {
    		if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
    		x = fa[top[x]];
    	}
    	return dep[x] > dep[y] ? y : x;
    }
    void modify(int x, int y, int z) {
    	while (top[x] != top[y]) {
    		if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
    		SgT::modify(dfn[top[x]], dfn[x], z);
    		x = fa[top[x]];
    	}
    	if (dep[x] > dep[y]) std::swap(x, y);
    	SgT::modify(dfn[x], dfn[y], z);
    }
    inline int query(int x) {
    	if (root == x) return SgT::query(1, n);
    	if (LCA(x, root) != x) return SgT::query(dfn[x], dfn[x] + sz[x] - 1);
    	const int S = get_son(root, x), l = dfn[S], r = dfn[S] + sz[S] - 1;
    	int ans = inf;
    	if (1 < l) ans = SgT::query(1, l - 1);
    	if (r < n) ans = std::min(ans, SgT::query(r + 1, n));
    	return ans;
    }
    
    int main() {
    	std::cin >> n >> m;
    	for (int i = 1, a, b; i < n; i++) {
    		std::cin >> a >> b;
    		addedge(a, b);
    	}
    	dfs1(1);
    	dfs2(top[1] = 1);
    	for (int i = 1; i <= n; i++) std::cin >> w[i];
    	for (int i = 1; i <= n; i++) W[dfn[i]] = w[i];
    	SgT::build(1, 1, n);
    	std::cin >> root;
    	while (m --> 0) {
    		int op, u, v, x;
    		std::cin >> op >> u;
    		switch (op) {
    			case 1:
    				root = u;
    				break;
    			case 2:
    				std::cin >> v >> x;
    				modify(u, v, x);
    				break;
    			case 3:
    				std::cout << query(u) << '
    ';
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Python subprocess方法
    Python hashlib、hmac加密模块
    mysql binlog详解
    Nginx 关键字详解
    账号笔记
    Python configparser模块
    Python yaml处理
    Linux && 与 ||
    spring boot 学习(十一)使用@Async实现异步调用
    spring boot 学习(十)SpringBoot配置发送Email
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10158745.html
Copyright © 2011-2022 走看看