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\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 遥远的国度 树链剖分的更多相关文章
- BZOJ 3083 遥远的国度 树链剖分
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 797 Solved: 181[Submit][Status] Descrip ...
- BZOJ 3083 遥远的国度(树链剖分+LCA)
Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...
- 【bzoj3083】遥远的国度 树链剖分+线段树
题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...
- BZOJ 3083: 遥远的国度(树链剖分+DFS序)
可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...
- BZOJ 3083 遥远的国度 树链剖分+线段树
有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...
- 洛谷P3979 遥远的国度 树链剖分+分类讨论
题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...
- BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 1280 MBSubmit: 3127 Solved: 795[Submit][Status][Discu ...
- [日常摸鱼]bzoj3083遥远的国度-树链剖分
一无聊就找树剖写 题意:一颗带点权的树,三种操作:1.换根 2.链赋值 3.查询子树最小值 如果没有换根的话直接就是裸的树剖了,对于换根的操作我们可以分类讨论. 1.如果查询的$x$就是根,那答案就是 ...
- BZOJ 3083 遥远的国度 树链剖分+脑子
唉..又调了半天QWQ..为何读入挂了.....莫非读入是反着的????据ywy学长所言如是...OvO震惊 这啥骚题啊...还要换根...不过清明讲过...(然鹅我现在才做... 先随便选个点(比如 ...
随机推荐
- JS合并单元格
在Web中经常需要合并单元格,例如对于下面一个表格: <!DOCTYPE html> <html> <head> <meta charset="UT ...
- imperva命令行查看流量值大小
watch -d -n 1 /proc/hades/status echo clear > /proc/hades/status //清除这些记录
- Office DDE漏洞学习笔记
1.前言 2017年下半年爆发出来的Office漏洞,一直没有空做笔记记录.在病毒分析中也看到有利用这个漏洞的样本,针对Office系列软件发起的钓鱼攻击和APT攻击一直是安全攻防的热点. 2.off ...
- video标签、audio标签
1.video标签 <video src="nans.mp4" controls="controls" autoplay="autoplay& ...
- haproxy支持的负载均衡算法详解
目前haproxy支持的负载均衡算法有如下8种: 1.roundrobin 表示简单的轮询,每个服务器根据权重轮流使用,在服务器的处理时间平均分配的情况下这是最流畅和公平的算法.该算法是动态的,对于实 ...
- linux文件管理 -> 系统目录结构
几乎所有的计算机操作系统都是用目录结构组织文件.具体来说就是在一个目录中存放子目录和文件, 而在子目录中又会进一步存放子目录和文件,以此类推形成一个树状的文件结构,由于其结构很像一棵树的分支, 所以该 ...
- spring学习之一概念
概念 1.是开源的轻量级框架 2.是一站式框架,就是说在java ee的三层结构中,每一层它都提供了不同的解决技术 web层:springMVC servoce层:spring IOC ,控制反转,通 ...
- 用js面向对象思想封装插件
js是基于原型的面向对象语言,如果你学过java,c#等正统面向对象语言,你会难以理解js的面向对象,他和普通的面向对象不太一样,今天,我们通过封装一个toast插件,来看看js面向对象是如何运行的. ...
- 学习总结——JMeter做http接口功能测试
JMeter对各种类型接口的测试 默认做接口测试前,已经给出明确的接口文档(如,http://test.nnzhp.cn/wiki/index.php?doc-view-59):本地配好了JMeter ...
- Django API验证(令牌)
1. 获取接口信息 Client端 import requests import time import hashlib ctime = time.time() key = 'akfljakfjakl ...