「LuoguP3979」遥远的国度
传送门
Luogu
解题思路
带换根操作的树剖。
换根只会影响更新或查询子树信息的操作。
我们始终保持初始的根不变,然后只要分类讨论一下:
假设当前被查询的节点是 \(u\)
- 如果 \(u\) 就是根节点,直接询问整棵树;
- 如果 \(u\) 不是根,且不是初始根的祖先,直接查询子树即可;
- 如果 \(u\) 是根的祖先,那么我们就找到 \(u\) 到根这条路径上的第一个儿子,然后分开查询即可
至于怎么分开查询,自己yy一下就好了。
细节注意事项
- 咕咕咕
参考代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while (!isdigit(c)) f |= (c == '-'), c = getchar();
while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
s = f ? -s : s;
}
const int _ = 100010;
int tot, head[_], nxt[_ << 1], ver[_ << 1];
inline void Add_edge(int u, int v)
{ nxt[++tot] = head[u], head[u] = tot, ver[tot] = v; }
int n, m, rt, val[_];
int dep[_], siz[_], son[_], fa[_];
int top[_], dfn[_], rev[_];
int mn[_ << 2], tag[_ << 2];
inline int lc(int p) { return p << 1; }
inline int rc(int p) { return p << 1 | 1; }
inline void pushup(int p) { mn[p] = min(mn[lc(p)], mn[rc(p)]); }
inline void f(int p, int v) { mn[p] = tag[p] = v; }
inline void pushdown(int p)
{ if (tag[p]) f(lc(p), tag[p]), f(rc(p), tag[p]), tag[p] = 0; }
inline void build(int p = 1, int l = 1, int r = n) {
tag[p] = 0; if (l == r) { mn[p] = val[rev[l]]; return ; }
int mid = (l + r) >> 1;
build(lc(p), l, mid), build(rc(p), mid + 1, r), pushup(p);
}
inline void update(int ql, int qr, int v, int p = 1, int l = 1, int r = n) {
if (ql <= l && r <= qr) return f(p, v);
int mid = (l + r) >> 1;
pushdown(p);
if (ql <= mid) update(ql, qr, v, lc(p), l, mid);
if (qr > mid) update(ql, qr, v, rc(p), mid + 1, r);
pushup(p);
}
inline int query(int ql, int qr, int p = 1, int l = 1, int r = n) {
if (ql <= l && r <= qr) return mn[p];
int mid = (l + r) >> 1, res = 2147483647;
pushdown(p);
if (ql <= mid) res = min(res, query(ql, qr, lc(p), l, mid));
if (qr > mid) res = min(res, query(ql, qr, rc(p), mid + 1, r));
return res;
}
inline void dfs1(int u, int f) {
siz[u] = 1, fa[u] = f, dep[u] = dep[f] + 1;
for (rg int v, i = head[u]; i; i = nxt[i])
if (!dep[v = ver[i]]) {
dfs1(v, u), siz[u] += siz[v];
if (siz[son[u]] < siz[v]) son[u] = v;
}
}
inline void dfs2(int u, int topf) {
top[rev[dfn[u] = ++dfn[0]] = u] = topf;
if (!son[u]) return; dfs2(son[u], topf);
for (rg int v, i = head[u]; i; i = nxt[i])
if (!top[v = ver[i]]) dfs2(v, v);
}
inline int pson(int x, int y){
int fx = top[x], fy = top[y];
while (fx != fy){
if (dep[fx] < dep[fy]) swap(x, y), swap(fx, fy);
if (fa[fx] == y) return fx; x = fa[fx], fx = top[x];
}
return dep[x] < dep[y] ? son[x] : son[y];
}
inline int LCA(int x, int y) {
int fx = top[x], fy = top[y];
while (fx != fy) {
if (dep[fx] < dep[fy]) swap(x, y), swap(fx, fy);
x = fa[fx], fx = top[x];
}
return dep[x] < dep[y] ? x : y;
}
inline void uptRange(int x, int y, int v) {
int fx = top[x], fy = top[y];
while (fx != fy) {
if (dep[fx] < dep[fy]) swap(x, y), swap(fx, fy);
update(dfn[fx], dfn[x], v), x = fa[fx], fx = top[x];
}
if (dep[x] > dep[y]) swap(x, y);
return update(dfn[x], dfn[y], v);
}
inline int qSon(int x) {
if (rt == x) return query(1, n);
int lca = LCA(rt, x);
if (lca != x) return query(dfn[x], dfn[x] + siz[x] - 1);
int t = pson(rt, x);
return min(query(1, dfn[t] - 1), query(dfn[t] + siz[t], n));
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
read(n), read(m);
for (rg int u, v, i = 1; i < n; ++i)
read(u), read(v), Add_edge(u, v), Add_edge(v, u);
for (rg int i = 1; i <= n; ++i) read(val[i]);
read(rt), dfs1(rt, 0), dfs2(rt, rt), build();
for (int opt, x, y, v; m--; ) {
read(opt);
if (opt == 1) read(rt);
else if (opt == 2) read(x), read(y), read(v), uptRange(x, y, v);
else if (opt == 3) read(x), printf("%d\n", qSon(x));
}
return 0;
}
完结撒花 \(qwq\)
「LuoguP3979」遥远的国度的更多相关文章
- 「BZOJ3083」遥远的国度(树剖换根
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 4859 Solved: 1372[Submit][Status][Discu ...
- 「译」JUnit 5 系列:条件测试
原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...
- 「译」JUnit 5 系列:扩展模型(Extension Model)
原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...
- JavaScript OOP 之「创建对象」
工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...
- 「C++」理解智能指针
维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...
- 「JavaScript」四种跨域方式详解
超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...
- 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management
写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...
- 「2014-3-18」multi-pattern string match using aho-corasick
我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...
- 「2014-3-17」C pointer again …
记录一个比较基础的东东-- C 语言的指针,一直让人又爱又恨,爱它的人觉得它既灵活又强大,恨它的人觉得它太过于灵活太过于强大以至于容易将人绕晕.最早接触 C 语言,还是在刚进入大学的时候,算起来有好些 ...
随机推荐
- 【知识学习】Sublime Text 快捷键精华版
Sublime Text 快捷键精华版 Ctrl+Shift+P:打开命令面板 Ctrl+P:搜索项目中的文件 Ctrl+G:跳转到第几行 Ctrl+W:关闭当前打开文件 Ctrl+Shift+W:关 ...
- MediaCreationTool制作WIN10安装U盘,安装纯净版win10的通用教程
注意: 1.准备8G或8G以上U盘. 2.安装系统前备份好个人需要数据(制作U盘会格式化U盘,U盘内有需要的数据也事先备份好) 3.有预装office的务必记住自己激活office账户和密码以免重装后 ...
- Cisco AP-Regulatory Domain
这一note主要解释Regulatory Domain是什么.以较新的思科AP的型号举例,思科AP的PID一般都是按照如下的命名: AIR-AP3802I-H-K9C 按照自己的理解: AIR:其中的 ...
- 关于java继承条件下的构造方法调用
首先是测试代码: class Grandparent { public Grandparent() { System.out.println("GrandParent Created.&qu ...
- Update(Stage4):sparksql:第3节 Dataset (DataFrame) 的基础操作 & 第4节 SparkSQL_聚合操作_连接操作
8. Dataset (DataFrame) 的基础操作 8.1. 有类型操作 8.2. 无类型转换 8.5. Column 对象 9. 缺失值处理 10. 聚合 11. 连接 8. Dataset ...
- uniGUI学习汇总
UniGUI之UniLabel(31) uniGUI之自定义JS事件动作ClientEvents(30) uniGUI之文件下载(29) uniGUI之FDQuery(28) uniGUI之UniPo ...
- 工具 - VS Code
杂项 1. 主题 brackets light pro, One Monokai theme 2. directory tree indent guidelines, directory vertic ...
- 数据包报文格式(IP包、TCP报头、UDP报头)
转自: https://blog.51cto.com/lyhbwwk/2162568 一.IP包格式 IP数据包是一种可变长分组,它由首部和数据负载两部分组成.首部长度一般为20-60字节(Byte) ...
- linux文件的类型和后缀名
还是以下图的install.log文件为例,第一栏的第一个字符为“-”代表install.log为正规档案 在linux系统中一般的档案类型为: 正规档案: 如install.log,一般的讲正规档案 ...
- 使用SQL语句还原数据库 2012.3.20
--返回由备份集内包含的数据库和日志文件列表组成的结果集. --主要获得逻辑文件名 USE master RESTORE FILELISTONLY FROM DISK = 'g:\back.Bak' ...