zoukankan      html  css  js  c++  java
  • luoguP3979 遥远的国度 树链剖分


    (1, 2)操作没什么好说的

    对于(3)操作,分三种情况讨论下

    (id = rt)的情况下,查整棵树的最小值即可

    如果(rt)(1)号点为根的情况下不在(id)的子树中,那么查(1)号点为根的情况下(id)的子树即可

    否则,找到(rt)(id)链中(id)的儿子,整棵树去掉这个子树就是(id)新的子树


    然而我太懒了,不想打倍增

    于是我们考虑用树剖来解决这个问题

    分两种情况

    如果最后(id)(id)的儿子处于一条重链,那么返回(son[id])

    否则,返回最后访问的轻链顶


    复杂度(O(n log^2 n))


    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define ri register int
    #define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
    #define drep(io, ed, st) for(ri io = ed; io >= st; io --)
    
    #define gc getchar
    inline int read() {
    	int p = 0, w = 1; char c = gc();
    	while(c < '0' || c > '9') { if(c == '-') w = -1; c = gc(); }
    	while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
    	return p * w;
    }
    	
    const int sid = 4e5 + 5;
    	
    int n, m, rt, id, cnp;
    int cap[sid], nxt[sid], node[sid];
    int anc[sid], val[sid], grd[sid], ind[sid], dfn[sid];
    int sz[sid], dep[sid], cov[sid], fa[sid], son[sid];
    	
    inline void addedge(int u, int v) {
    	nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v;
    }
    	
    #define cur node[i]
    inline void dfs(int o) {
    	sz[o] = 1; 
    	for(int i = cap[o]; i; i = nxt[i])
    		if(cur != fa[o]) {
    			fa[cur] = o;
    			dep[cur] = dep[o] + 1;
    			dfs(cur);
    			sz[o] += sz[cur];
    			if(sz[cur] > sz[son[o]]) son[o] = cur;
    		}
    }
    
    inline void dfs(int o, int ac) {
    	anc[o] = ac; dfn[o] = ++ id; ind[id] = o;
    	if(!son[o]) return;
    	dfs(son[o], ac);
    	for(int i = cap[o]; i; i = nxt[i])
    		if(cur != fa[o] && cur != son[o])
    			dfs(cur, cur);
    }
    	
    #define ls (o << 1)
    #define rs (o << 1 | 1)
    	
    inline void build(int o, int l, int r) {
    	if(l == r) { val[o] = grd[ind[l]]; return; }
    	int mid = (l + r) >> 1;
    	build(ls, l, mid); build(rs, mid + 1, r);
    	val[o] = min(val[ls], val[rs]);
    }
    	
    inline void pcov(int o, int v) {
    	val[o] = cov[o] = v;
    }
    	
    inline void pushcov(int o) {
    	if(!cov[o]) return;
    	pcov(ls, cov[o]); pcov(rs, cov[o]);
    	cov[o] = 0;
    }
    
    inline void mdf(int o, int l, int r, int ml, int mr, int v) {
    	if(ml > r || mr < l) return;
    	if(ml <= l && mr >= r) { pcov(o, v); return; }
    	pushcov(o);
    	int mid = (l + r) >> 1;
    	mdf(ls, l, mid, ml, mr, v);
    	mdf(rs, mid + 1, r, ml, mr, v);
    	val[o] = min(val[ls], val[rs]);
    }
    
    const int inf = 2147483647;
    inline int qry(int o, int l, int r, int ml, int mr) {
    	if(ml > r || mr < l || ml > mr) return inf;
    	if(ml <= l && mr >= r) return val[o];
    	pushcov(o);
    	int mid = (l + r) >> 1;
    	return min(qry(ls, l, mid, ml, mr), qry(rs, mid + 1, r, ml, mr));
    }
    
    inline void mdf(int u, int v, int w) {
    	int pu = anc[u], pv = anc[v];
    	while(pu != pv) {
    		if(dep[pu] < dep[pv]) swap(u, v), swap(pu, pv);
    		mdf(1, 1, n, dfn[pu], dfn[u], w);
    		u = fa[pu]; pu = anc[u];
    	}
    	if(dep[u] > dep[v]) swap(u, v);
    	mdf(1, 1, n, dfn[u], dfn[v], w);
    }
    
    inline int up(int o, int top) {
    	int po = anc[o], pv = anc[top];
    	while(po != pv) {
    		if(fa[po] == top) return po;
    		o = fa[po]; po = anc[o];
    	}
    	return son[top];
    }
    
    int main() {
    	n = read(); m = read();
    	rep(i, 2, n) {
    		int u = read(), v = read();
    		addedge(u, v); addedge(v, u);
    	}
    	rep(i, 1, n) grd[i] = read();
    	dfs(1); dfs(1, 1); build(1, 1, n);
    	rt = read();
    	rep(i, 1, m) {
    		int opt = read();
    		if(opt == 1) rt = read();
    		else if(opt == 2) {
    			int u = read(), v = read(), w = read();
    			mdf(u, v, w);
    		}
    		else {
    			int ip = read();
    			if(ip == rt) printf("%d
    ", val[1]);
    			else {
    				if(dfn[ip] <= dfn[rt] && dfn[rt] <= dfn[ip] + sz[ip] - 1) {
    					int t = up(rt, ip);
    					printf("%d
    ", min(qry(1, 1, n, 1, dfn[t] - 1), qry(1, 1, n, dfn[t] + sz[t], n)));
    				}
    				else printf("%d
    ", qry(1, 1, n, dfn[ip], dfn[ip] + sz[ip] - 1));
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    敢为技术定坤乾
    蒙古包作客有感
    少时儿伴他乡遇
    花漫锦宫城
    游红原大草原有感
    把日子过成一首诗
    Request.UrlReferrer详解
    INFO: HTTP GET and HTTP POST Are Disabled by Default
    请求因 HTTP 状态 401 失败:Access Denied。
    SoapRpcMethod.OneWay相关
  • 原文地址:https://www.cnblogs.com/reverymoon/p/10140605.html
Copyright © 2011-2022 走看看