\(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\n", val[1]);
else {
if(dfn[ip] <= dfn[rt] && dfn[rt] <= dfn[ip] + sz[ip] - 1) {
int t = up(rt, ip);
printf("%d\n", min(qry(1, 1, n, 1, dfn[t] - 1), qry(1, 1, n, dfn[t] + sz[t], n)));
}
else printf("%d\n", qry(1, 1, n, dfn[ip], dfn[ip] + sz[ip] - 1));
}
}
}
return 0;
}

luoguP3979 遥远的国度 树链剖分的更多相关文章

  1. BZOJ 3083 遥远的国度 树链剖分

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 797  Solved: 181[Submit][Status] Descrip ...

  2. BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...

  3. 【bzoj3083】遥远的国度 树链剖分+线段树

    题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...

  4. BZOJ 3083: 遥远的国度(树链剖分+DFS序)

    可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...

  5. BZOJ 3083 遥远的国度 树链剖分+线段树

    有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...

  6. 洛谷P3979 遥远的国度 树链剖分+分类讨论

    题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...

  7. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  8. [日常摸鱼]bzoj3083遥远的国度-树链剖分

    一无聊就找树剖写 题意:一颗带点权的树,三种操作:1.换根 2.链赋值 3.查询子树最小值 如果没有换根的话直接就是裸的树剖了,对于换根的操作我们可以分类讨论. 1.如果查询的$x$就是根,那答案就是 ...

  9. BZOJ 3083 遥远的国度 树链剖分+脑子

    唉..又调了半天QWQ..为何读入挂了.....莫非读入是反着的????据ywy学长所言如是...OvO震惊 这啥骚题啊...还要换根...不过清明讲过...(然鹅我现在才做... 先随便选个点(比如 ...

随机推荐

  1. 使用转义防御XSS

    使用转义防御XSS 在输出的时候防御XSS即对用户输入进行转义,XSS的问题本质上还是代码注入,HTML或者javascript的代码注入,即混淆了用户输入的数据和代码.而解决这个问题,就需要根据用户 ...

  2. 【NOIP题解】NOIP2017 TG D2T3 列队

    列队,NOIP2017 TG D2T3. 树状数组经典题. 题目链接:洛谷. 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. ...

  3. JDk1.8源码StringBuffer

    一.概念 StringBuffer A thread-safe, mutable sequence of characters. A string buffer is like a {@link St ...

  4. JavaScript 金额、数字、千分位、千分位、保留几位小数、舍入舍去、支持负数

    JavaScript 金额.数字 千分位格式化.保留指定位数小数.支持四舍五入.进一法.去尾法 字段说明: number:需要处理的数字: decimals:保留几位小数,默认两位,可不传: dec_ ...

  5. MySQL分布式集群之MyCAT(二)【转】

    在第一部分,有简单的介绍MyCAT的搭建和配置文件的基本情况,这一篇详细介绍schema的一些具体参数,以及实际作用        首先贴上自己测试用的schema文件,双引号之前的反斜杠不会消除,姑 ...

  6. C#中HttpWebRequest的GetRequestStream执行的效率太低,甚至偶尔死掉

    为了提高httpwebrequest的执行效率,查到了一些如下设置 request.ServicePoint.Expect100Continue = false; request.ServicePoi ...

  7. mysql命令补全工具

    需要在linux中下载mysql插件. 安装mysql插件 yum -y install epel-release python-pip python-devel pip install mycli ...

  8. 在Eclipse中建立Maven工程

  9. git —— 分支冲突

    解决冲突 冲突需手动解决 $ git status 查看冲突的文件 <<<<<<<,=======,>>>>>>> ...

  10. 洛谷P1841重要的城市

    传送门啦 重要城市有三个性质如下: 1.重要城市能对其他两个不同城市的最短路径做出贡献 2.重要城市具有唯一性,如果两不同城市之间的最短路径有两种中间城市情况,那么这两个中间城市可以彼此代替,就都不能 ...