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;
    }
    
  • 相关阅读:
    STM32 F4 DAC DMA Waveform Generator
    STM32 F4 General-purpose Timers for Periodic Interrupts
    Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式
    Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块
    查看SQL Server服务运行帐户和SQL Server的所有注册表项
    Pycharm使用技巧(转载)
    SQL Server 2014内存优化表的使用场景
    Python第十天 print >> f,和fd.write()的区别 stdout的buffer 标准输入 标准输出 从控制台重定向到文件 标准错误 重定向 输出流和输入流 捕获sys.exit()调用 optparse argparse
    Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
    Python第六天 类型转换
  • 原文地址:https://www.cnblogs.com/reverymoon/p/10140605.html
Copyright © 2011-2022 走看看