luoguP3979 遥远的国度
换根的树剖
https://www.luogu.org/problem/P3979
题意:
(出题人口活好....
给定一棵以 root 为根的 n 个点的有根树,对于任意一个点 x, 给定他
的点权 val。
现在请你完成以下操作
• 1 x 表示把当前有根树的根换为 x
• 2 x y val 表示把从 x 到 y 路径上的点点权设置为 val
• 3 x 询问 x 的子树内(包括 x)点权的最小值,并输出最小值。
分析
我们直接来考虑换根操作:
首先,dfs重新树剖是不现实的。然后,操作2和换根没啥关系,直接做。
所以我们直接考虑操作3,先对点1进行树剖,再设当前的根是root。
- 当x==root:全局最小,直接输出。 
- 当x是root在以1为根情况下的子树:谁是根对这个x的子树没有影响 
- x不属于以上情况,但也不在1到root的链上,而在其他的支叉上:还是木有影响,自己手胡以下吧 
- x在1到root的链上:这就是要处理的重点了。 
先不管怎么求min,先看看分别该什么时候求min:
1就直接判断完事,2和3性质一样,而且4的条件最好判断(只要lca(x,root)==x即可),所以我们可以先判断4,剩下的就是2或3,即剩下的直接输出
考虑操作4, 在以1为根的情况下,我们如果要求x的子树信息,我们查询的是[in[x], out[x]]这段区间,而在以root为根的情况下,我们如果要求x的子树信息,那我们没有求的是那一段? 是x在root方向上的亲儿子及其子树。所以我们只需要找到这个亲儿子(我把它形象的成为最近公共儿子lcs), 然后查找区间[1, in[lcs]-1] ∪ [out[lcs]+1, n] 的信息即可
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100000+9;
const int MAXM = MAXN<<1;
#define ll long long
#define inf 21474836489
int n,m,root;
struct node{
	int deep, size, son, fa, tp ,in, out;
}a[MAXN];
int _clock;
int head[MAXN], cnt;
struct seg{
	int y, nxt;
}e[MAXM];
void add_edge(int x, int y) {
	e[++cnt].y = y;
	e[cnt].nxt = head[x];
	head[x] = cnt;
}
void dfs1(int x, int fa) {
	a[x].fa = fa;
	a[x].deep = a[fa].deep + 1;
	a[x].size = 1;
	for(int i = head[x]; i; i = e[i].nxt)
	 	if(e[i].y != fa) {
			dfs1(e[i].y, x);
			a[x].size += a[e[i].y].size;
			a[x].son = a[a[x].son].size > a[e[i].y].size ? a[x].son : e[i].y;
		}
}
ll arr[MAXN], pos[MAXN];
void dfs2(int x, int tp) {
	a[x].tp = tp;
	a[x].in = ++_clock;
	pos[_clock] = arr[x];
	if(a[x].son) dfs2(a[x].son, tp);
	for(int i = head[x]; i; i = e[i].nxt)
		if(e[i].y != a[x].fa && e[i].y != a[x].son) dfs2(e[i].y, e[i].y);
	a[x].out = _clock;
}
struct tree{
	ll mi, set;
}tr[MAXN<<2];
void pushup(int o) {tr[o].mi = min(tr[o<<1].mi , tr[o<<1|1].mi);}
void build(int o, int l, int r) {
	tr[o].set = -1;
	if(l == r) {
		tr[o].mi = pos[l];
		return ;
	}
	int mid = (l+r)>>1;
	build(o<<1, l, mid);
	build(o<<1|1, mid+1, r);
	pushup(o);
}
void pushdown(int o) {
	if(tr[o].set == -1) return ;
	tr[o<<1].mi = tr[o<<1|1].mi = tr[o<<1].set = tr[o<<1|1].set = tr[o].set;
	tr[o].set = -1;
}
void optset(int o, int l, int r, int ql, int qr, ll k) {
	if(ql <= l && r <= qr) {
		tr[o].set = tr[o].mi = k;
		return ;
	}
	int mid = (l+r)>>1;
	pushdown(o);
	if(ql <= mid) optset(o<<1, l, mid, ql, qr, k);
	if(mid < qr) optset(o<<1|1, mid+1, r, ql, qr, k);
	pushup(o);
}
ll query(int o, int l, int r, int ql, int qr) {
	if(ql <= l && r <= qr) return tr[o].mi;
	int mid = (l+r)>>1;
	pushdown(o);
	ll ans = inf;
	if(ql <= mid) ans = min(ans, query(o<<1, l, mid, ql, qr));
	if(mid < qr) ans = min(ans, query(o<<1|1, mid+1, r, ql, qr));
	return ans;
}
void ttt_update(int x, int y, ll z) {
	while(a[x].tp != a[y].tp) {
		if(a[a[x].tp].deep < a[a[y].tp].deep) swap(x,y);
		optset(1, 1, n, a[a[x].tp].in, a[x].in, z);
		x = a[a[x].tp].fa ;
	}
	if(a[x].deep > a[y].deep) swap(x,y);
	optset(1, 1, n, a[x].in, a[y].in, z);
}
int lca(int x, int y) {
	while(a[x].tp != a[y].tp) {
		if(a[a[x].tp].deep < a[a[y].tp].deep) swap(x,y);
		x = a[a[x].tp].fa;
	}
	return a[x].deep < a[y].deep ? x : y;
}
int find_lcs(int x, int y) {//找x到y方向上的亲儿子
	int last;
	while(a[y].tp != a[x].tp) {
		last = a[y].tp;
		y = a[a[y].tp].fa;
	}
	if(y != x) last = a[x].son;
	return last;
}
int main() {
	scanf("%d%d",&n,&m);
	int x,y;
	for(int i = 1; i < n; i++) {
		scanf("%d%d",&x,&y);
		add_edge(x,y);
		add_edge(y,x);
	}
	for(int i = 1; i <= n; i++) scanf("%lld",&arr[i]);
	scanf("%d",&root);
	dfs1(1, 0);
	dfs2(1, 1);
	build(1, 1, n);
	ll z;
	int cmd;
	int son;
	for(int i = 1; i <= m; i++) {
		scanf("%d",&cmd);
		if(cmd == 1) {
			scanf("%d", &root);
		} else if(cmd == 2) {
			scanf("%d%d%lld",&x,&y,&z);
			ttt_update(x, y, z);
		} else {
			scanf("%d",&x);
			if(x == root) printf("%lld\n", tr[1].mi);
			else if(lca(x, root) == x) {
				son = find_lcs(x, root);
				printf("%lld\n",min(query(1, 1, n, 1, a[son].in-1), query(1, 1, n, a[son].out+1, n)) );
			} else printf("%lld\n",query(1, 1, n, a[x].in, a[x].out));
		}
	}
}
luoguP3979 遥远的国度的更多相关文章
- luoguP3979 遥远的国度  LCT+multiset维护子树信息
		Code: #include<bits/stdc++.h> #define maxn 150000 #define ll long long #define inf 21474836470 ... 
- luoguP3979 遥远的国度 树链剖分
		\(1, 2\)操作没什么好说的 对于\(3\)操作,分三种情况讨论下 \(id = rt\)的情况下,查整棵树的最小值即可 如果\(rt\)在\(1\)号点为根的情况下不在\(id\)的子树中,那么 ... 
- 「LuoguP3979」遥远的国度
		传送门 Luogu 解题思路 带换根操作的树剖. 换根只会影响更新或查询子树信息的操作. 我们始终保持初始的根不变,然后只要分类讨论一下: 假设当前被查询的节点是 \(u\) 如果 \(u\) 就是根 ... 
- BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]
		3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 1280 MBSubmit: 3127 Solved: 795[Submit][Status][Discu ... 
- BZOJ 3083: 遥远的国度  dfs序,树链剖分,倍增
		今天再做一天树的题目,明天要开始专攻图论了.做图论十几天之后再把字符串搞搞,区域赛前再把计几看看. 3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 ... 
- BZOJ 3083 遥远的国度 树链剖分
		3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 797 Solved: 181[Submit][Status] Descrip ... 
- BZOJ_3083_遥远的国度_树链剖分+线段树
		BZOJ_3083_遥远的国度_树链剖分 Description 描述 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神Ra ... 
- [luogu3979][bzoj3083]遥远的国度
		[luogu传送门] [bzoj传送门] 题目描述 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcww ... 
- P3979 遥远的国度
		P3979 遥远的国度 思路 一开始我用这个函数得到左端点 int get_l(int x,int y) { if(top[x]==top[y]) return son[x]; int last=to ... 
随机推荐
- 初识Kotlin之函数
			本章通过介绍Kotlin的基本函数,默认参数函数,参数不定长函数,尾递归函数,高阶函数,Lamdba表达式.来对Kotlin函数做进一步了解.将上一篇的Kotlin变量的知识得以运用.Kotlin变量 ... 
- android-ramdisk.img分析、recovery.img&boot.img执行过程【转】
			一.ramdisk介绍 ramdisk通过直面意思就大概能理解意思,ram disk虚拟内存盘,将ram模拟成硬盘来使用的文件系统.对于传统的磁盘文件系统来说,这样做的好处是可以极大提高文件访问速度: ... 
- postman---postman提示 Could not get any response
			在通过postman请求做接口测试的过程中,有时候会遇到一些报错,当遇到这些报错我们不要着急,看着具体哪里报错,然后进行解决 postman报错 经常使用postman的小伙伴们都应该遇到过一些报错, ... 
- 201871010132-张潇潇《面向对象程序设计(java)》第一周学习总结
			面向对象程序设计(Java) 博文正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cn ... 
- deepin/debian 安装docker
			简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会 ... 
- AcWing 836. 合并集合
			地址 https://www.acwing.com/problem/content/838/ 一共有n个数,编号是1~n,最开始每个数各自在一个集合中. 现在要进行m个操作,操作共有两种: “M a ... 
- bzoj 5218: [Lydsy2017省队十连测]友好城市
			题意: 这题显然直接tarjan是做不了的. 这里安利另一个求SCC的算法Kosaraju,学习的话可以见这篇博客 于是结合莫队,我们有了个暴力. 发现主要瓶颈是dfs过程中找最小的未经过的点,我们用 ... 
- 《大数据技术应用与原理》第二版-第三章分布式文件系统HDFS
			3.1分布式文件 HDFS默认一个块的大小是64MB,与普通文件不同的是如果一个文件小于数据块的大小,它并不占用整个数据块的存储空间. 主节点又叫名称节点:另一个叫从节点又叫数据节点.名称节点负责文件 ... 
- 关于js里的那一堆事件
			分类 事件名 触发描述 一般事件 onclick 鼠标点击事件 ondbclick 鼠标双击事件 onmousedown/up 鼠标按下/松开事件 onmouseover/move/out 鼠标悬浮/ ... 
- 图像处理-裁剪具有透明背景的png
			我遇到了需要裁剪具有透明背景的png的问题,用 https://www.yasuotu.com/editor 这个压缩图网站解决了问题. 这里可以选择裁剪的宽度和高度,记得点击确定按钮. 裁剪完成后, ... 
