\(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. 【网页开发学习】Coursera课程《面向 Web 开发者的 HTML、CSS 与 Javascript》Week1课堂笔记

    Coursera课程<面向 Web 开发者的 HTML.CSS 与 Javascript> Johns Hopkins University Yaakov Chaikin Week1 In ...

  2. 15 Defer, Panic, and Recover

    Defer, Panic, and Recover 4 August 2010 Go has the usual mechanisms for control flow: if, for, switc ...

  3. http://code52.org/DownmarkerWPF/

    http://code52.org/DownmarkerWPF/ http://kb.cnblogs.com/page/132209/

  4. Python模块制作

    在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字. 定义自己的模块 比如有这样一个文件test.py,在test.py中定义了函数add def add(a,b): ...

  5. thinkphp模型实例化

    方法一 方法二

  6. 网络编程--Socket与ServerSocket

    1.服务器端代码 package net; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Sock ...

  7. 20165203 预备作业3 Linux安装及学习

    一.安装虚拟机 1.下载问题:当自己在虚拟机上下载ubuntu时,总是下载好长时间,而且最后下载失败,这让我很苦恼. 解决方案:求助同学后,同学给了我一个中文版官网的网址http://cn.ubunt ...

  8. ubuntu16.04 安装 caffe cuda 相关流程

    不多说了,经历了很多莫名其妙的错误最后终于安装好了,直接放安装脚本: #!/bin/bash #安装时要注意有些库可能安装失败以及安装caffe有和protobuf相关错误时可能需要重新对protob ...

  9. CTF中做Linux下漏洞利用的一些心得

    其实不是很爱搞Linux,但是因为CTF必须要接触一些,漏洞利用方面也是因为CTF基本都是linux的pwn题目. 基本的题目分类,我认为就下面这三种,这也是常见的类型. 下面就分类来说说 0x0.栈 ...

  10. OneNote无法同时设置中英文字体设置解决办法

    如果你是一位OneNote老用户,无论是2003.2007还是2010或者最新的2013版本,都一直存在一个Bug,就是无法同时设置中英文字体(比如在Word中就可以分别设置不同的).我搜了一下,在微 ...