\(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. Postman和Selenium IDE开局自带红蓝BUFF属性,就问你要还是不要

    话不多说,下面给大家介绍两款工具,selenium IDE和Postman. 为什么说是自带红蓝Buff,因为想做UI自动化和接口自动化的同学,很多时候,都难在了开头. 比如你要学习语言,你要学习框架 ...

  2. hdu 1716 排列2(DFS搜索)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1716 排列2 Time Limit: 1000/1000 MS (Java/Others)    Me ...

  3. 2016.5.16——leetcode:Rotate Array,Factorial Trailing Zeroe

    Rotate Array 本题目收获: 题目: Rotate an array of n elements to the right by k steps. For example, with n = ...

  4. git checkout 命令详解【转】

    转自:http://www.cnblogs.com/hutaoer/archive/2013/05/07/git_checkout.html 在日常的git操作中,git checkout——检出,是 ...

  5. linq和ef关于group by取最大值的两种写法

    LINQ: var temp = from p in db.jj_Credentials group p by p.ProfessionID into g select new { g.Key, Ma ...

  6. 从一个局长使用BS系统的无奈看测试点

    今天我点名买了个B/S系统,听说只要有浏览器就能用.我最讨厌装客户端了,用浏览器就是方便啊. 下面就是我使用这个系统碰到的麻烦事: 我登录失败的时候没有任何提示,这没什么,反正提示也只是说失败…… 进 ...

  7. Linux 网络编程实例

    /*socket->bind->listen->accept->recv/recvfrom->send/sendto->close 客户端:socket->c ...

  8. 使用JS实现2048小游戏

    JS实现2048小游戏源码 效果图: 代码如下,复制即可使用: (适用浏览器:360.FireFox.Chrome.Opera.傲游.搜狗.世界之窗. 不支持Safari.IE8及以下浏览器.) &l ...

  9. 使用html+css+js实现日历与定时器,看看今天的日期和今天剩余的时间。

    使用html+css+js实现日历与定时器,看看今天的日期和今天剩余的时间. 效果图: 哎,今天就又这么过去了,过的可真快 . 代码如下,复制即可使用: <!DOCTYPE html> & ...

  10. 奇妙的CSS之CSS3新特性总结

    随着CSS3标准的发布,越来越多的浏览器开始支持最新的CSS标准,虽然还有些新特性支持的不够完美,但相信未来的浏览器一定会完全支持CSS3的,毕竟这代表着大趋势!下面l列出来一些CSS3中出现的新特性 ...