zoukankan      html  css  js  c++  java
  • BZOJ 3083 遥远的国度 (换根讨论 + 树链剖分)

    题目链接  BZOJ3083

    换根不能真正地换。

    令当前的根为$cnt$,要查找的子树根为$x$

    $1$、$x = cnt$,那么要查找的区域就是整棵树。

    $2$、$x$在以$cnt$为根的子树内,那么要查找的区域就是以$x$为根的子树。

    $3$、$x$在以$cnt$为根的子树外

      (1)$x$不是$cnt$的祖先,那么要查找的区域就是以$x$为根的子树。

      (2)$x$是$cnt$的祖先,设$y$为$x$到$cnt$方向上的第一个点,那么要查找的区域就是整棵树减去以$y$为根的子树。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define	ls		i << 1
    #define	rs		i << 1 | 1
    #define	mid		((L + R) >> 1)
    #define lson		i << 1, L, mid
    #define rson		i << 1 | 1, mid + 1, R
    
    const int N = 1e5 + 10;
    
    int f[N], fp[N], son[N], deep[N], father[N], sz[N], a[N], top[N];
    int n, m, tot = 0;
    int cnt;
    int s[N << 2], lazy[N << 2];
    vector <int> v[N];
    
    void dfs1(int x, int fa, int dep){
    	deep[x] = dep;
    	father[x] = fa;
    	son[x] = 0;
    	sz[x] = 1;
    	int ct = (int)v[x].size();
    	rep(i, 0, ct - 1){
    		int u = v[x][i];
    		if (u == fa) continue;
    		dfs1(u, x, dep + 1);
    		sz[x] += sz[u];
    		if (sz[son[x]] < sz[u]) son[x] = u;
    	}
    }
    
    void dfs2(int x, int tp){
    	top[x] = tp;
    	f[x] = ++tot;
    	fp[f[x]] = x;
    	if (son[x]) dfs2(son[x], tp);
    	int ct = (int)v[x].size();
    	rep(i, 0, ct - 1){
    		int u = v[x][i];
    		if (u == father[x] || u == son[x]) continue;
    		dfs2(u, u);
    	}
    }
    
    inline void pushup(int i){ s[i] = min(s[ls], s[rs]); }
    
    inline void pushdown(int i){
    	if (lazy[i]){
    		s[ls] = lazy[ls] = lazy[i];
    		s[rs] = lazy[rs] = lazy[i];
    		lazy[i] = 0;
    	}
    }
    
    void update(int i, int L, int R, int l, int r, int val){
    	if (l <= L && R <= r){
    		s[i] = lazy[i] = val;
    		return;
    	}
    
    	pushdown(i);
    	if (l <= mid) update(lson, l, r, val);
    	if (r >  mid) update(rson, l, r, val);
    	pushup(i);
    }
    
    int query(int i, int L, int R, int l, int r){
    	if (l <= L && R <= r) return s[i];
    
    	pushdown(i);
    	int ret = INT_MAX;
    	if (l <= mid) ret = min(ret, query(lson, l, r));
    	if (r >  mid) ret = min(ret, query(rson, l, r));
    	return ret;
    }
    
    void modify(int x, int y, int val){
    	int f1 = top[x], f2 = top[y];
    	for (; f1 ^ f2; ){
    		if (deep[f1] < deep[f2]) swap(f1, f2), swap(x, y);
    		update(1, 1, n, f[f1], f[x], val);
    		x = father[f1], f1 = top[x];
    	}
    
    	if (x == y){
    		update(1, 1, n, f[x], f[y], val);
    		return;
    	}
    
    	if (deep[x] > deep[y]) swap(x, y);
    	update(1, 1, n, f[x], f[y], val);
    	return;
    
    }
    
    int twz(int x, int y){
    	int t;
    	for (; top[x] ^ top[y]; ) t = top[y], y = father[top[y]];
    	return x == y ? t : son[x];
    }
    
    int LCA(int x, int y){
    	for (; top[x] ^ top[y]; ){
    		if (deep[top[x]] < deep[top[y]]) swap(x, y);
    		x = father[top[x]];
    	}
    
    	return deep[x] > deep[y] ? y : x;
    }
    
    int main(){
    
    	scanf("%d%d", &n, &m);
    
    	rep(i, 0, 4e5 + 10) s[i] = INT_MAX;
    
    	rep(i, 2, n){
    		int x, y;
    		scanf("%d%d", &x, &y);
    		v[x].push_back(y);
    		v[y].push_back(x);
    	}
    
    	dfs1(1, 0, 1);
    	dfs2(1, 1);
    
    	rep(i, 1, n){
    		int x;
    		scanf("%d", &x);
    		update(1, 1, n, f[i], f[i], x);
    	}
    
    	scanf("%d", &cnt);
    
    	while (m--){
    		int op;
    		scanf("%d", &op);
    		if (op == 1) scanf("%d", &cnt);
    		else if (op == 2){
    			int x, y, z;
    			scanf("%d%d%d", &x, &y, &z);
    			modify(x, y, z);
    		}
    
    		else{
    			int x;
    			scanf("%d", &x);
    			if (x == cnt){
    				printf("%d
    ", query(1, 1, n, 1, n));
    				continue;
    			}
    
    			int lca = LCA(x, cnt);
    			if (lca == x){
    				int y = twz(x, cnt);
    				int ret = INT_MAX;
    				int xx  = f[y], yy = f[y] + sz[y] - 1;
    				if (xx >= 1) ret = min(ret, query(1, 1, n, 1, xx - 1));
    				if (yy <  n) ret = min(ret, query(1, 1, n, yy + 1, n));
    				printf("%d
    ", ret);
    				continue;
    			}
    
    			printf("%d
    ", query(1, 1, n, f[x], f[x] + sz[x] - 1));
    		}
    	}
    
    	return 0;
    }
    

      

  • 相关阅读:
    一个优秀测试的自我修养
    二.自动化接口测试---用例设计思路、模版
    关于文件读写的一些笔记
    模块导入---如何在一个文件中导入其它模块,来调用它的变量、函数等,以节省代码量
    变量以及作用域----(局部变量、全部变量...)
    python连接mysql数据库
    python修改txt文件内容
    使用PyQt4写界面后台程序方法总结
    unresolved import 解决办法
    怎样使用pyinstaller打包
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/8433936.html
Copyright © 2011-2022 走看看