2022-07-08 11:13阅读: 17评论: 0推荐: 0

P3979 遥远的国度

传送门

题目大意

一棵 n(1n105) 个节点的树,一开始给定了初始的根,每个节点上有权值 ai(0<ai<231)m(1m105) 次操作,共 3 种操作类型:
1 id :将 id 作为新的根
2 x y v :将 xy 路径上所有点权置为 v
3 id :查询当前以 id 为根的子树中节点权值的最小值

思路

如果没有换根操作,那么树剖后用线段树维护很容易解决。对于换根操作,无论根是谁,我们都只在一开始令 1 为根进行一次树剖,之后的换根可以分为几种情况,首先是如果查询的节点正好是当前的根,那么直接就是整棵树的信息,如果不是,那么还分为两种情况,考虑从 1root 的路径,如果查询的节点 id 不在这条路径上,查询仍然为以 1 为根时的以 id 为根的子树信息,如果在这条路径上,设 id 在这条路径上的儿子节点为 u ,那么查询的信息就是以 1 为根时整棵树的信息去掉以 u 为根节点的子树的信息。对于 u ,我们可以直接在树上跳链来寻找。

代码

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
using LL = long long;
using LD = long double;
using ULL = unsigned long long;
using PII = pair<int, int>;
using TP = tuple<int, int, int>;
#define all(x) x.begin(),x.end()
#define mst(x,v) memset(x,v,sizeof(x))
#define mk make_pair
//#define int LL
#define lc p*2
#define rc p*2+1
#define endl '\n'
#define inf INT_MAX
#define INF 0x3f3f3f3f3f3f3f3f
#pragma warning(disable : 4996)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const double eps = 1e-8;
const LL MOD = 1000000007;
const LL mod = 998244353;
const int maxn = 1000010;

int N, M, A[maxn], root;
vector<int>G[maxn];
int fa[maxn], dep[maxn], siz[maxn], hson[maxn], top[maxn], dfn[maxn], rnk[maxn], tot = 0;

void add_edge(int from, int to)
{
	G[from].push_back(to);
	G[to].push_back(from);
}

void dfs1(int v, int p, int d)
{
	fa[v] = p, dep[v] = d, siz[v] = 1;
	for (auto& to : G[v])
	{
		if (to == p)
			continue;
		dfs1(to, v, d + 1);
		siz[v] += siz[to];
		if (!hson[v] || siz[to] > siz[hson[v]])
			hson[v] = to;
	}
}

void dfs2(int v, int p, int t)
{
	dfn[v] = ++tot, rnk[tot] = v, top[v] = t;
	if (!hson[v])
		return;
	dfs2(hson[v], v, t);
	for (auto& to : G[v])
	{
		if (to == p || to == hson[v])
			continue;
		dfs2(to, v, to);
	}
}

int find(int v)
{
	int tmp = root;
	while (top[v] != top[tmp])
	{
		if (fa[top[tmp]] == v)
			return top[tmp];
		tmp = fa[top[tmp]];
		if (tmp == 0)
			return 0;
	}
	if (dfn[v] > dfn[tmp])
		return 0;
	return hson[v];
}

struct Node {
	int dat, l, r, lazy;
}tr[maxn * 4];

void pushup(int p)
{
	tr[p].dat = min(tr[lc].dat, tr[rc].dat);
}

void pushdown(int p)
{
	if (tr[p].lazy)
	{
		tr[lc].dat = tr[lc].lazy = tr[p].lazy;
		tr[rc].dat = tr[rc].lazy = tr[p].lazy;
		tr[p].lazy = 0;
	}
}

void build(int p, int l, int r)
{
	tr[p].l = l, tr[p].r = r;
	if (l + 1 == r)
	{
		tr[p].dat = A[rnk[l]];
		return;
	}
	int mid = (l + r) / 2;
	build(lc, l, mid), build(rc, mid, r);
	pushup(p);
}

void modify(int p, int l, int r, int val)
{
	if (tr[p].l >= l && tr[p].r <= r)
	{
		tr[p].dat = tr[p].lazy = val;
		return;
	}
	pushdown(p);
	int mid = (tr[p].l + tr[p].r) / 2;
	if (l < mid)
		modify(lc, l, r, val);
	if (r > mid)
		modify(rc, l, r, val);
	pushup(p);
}

int query(int p, int l, int r)
{
	if (tr[p].l >= l && tr[p].r <= r)
		return tr[p].dat;
	pushdown(p);
	int mid = (tr[p].l + tr[p].r) / 2;
	if (r <= mid)
		return query(lc, l, r);
	else if (l >= mid)
		return query(rc, l, r);
	else
		return min(query(lc, l, mid), query(rc, mid, r));
}

void solve()
{
	dfs1(1, 0, 1), dfs2(1, 0, 1);
	build(1, 1, N + 1);
	int op, id, x, v, y;
	while (M--)
	{
		cin >> op;
		if (op == 1)
		{
			cin >> id;
			root = id;
		}
		else if (op == 2)
		{
			cin >> x >> y >> v;
			while(top[x] != top[y])
			{
				if (dep[top[x]] > dep[top[y]])
					modify(1, dfn[top[x]], dfn[x] + 1, v), x = fa[top[x]];
				else
					modify(1, dfn[top[y]], dfn[y] + 1, v), y = fa[top[y]];
			}
			if (dfn[x] > dfn[y])
				swap(x, y);
			modify(1, dfn[x], dfn[y] + 1, v);
		}
		else
		{
			cin >> id;
			if (root == id)
				cout << query(1, 1, N + 1) << endl;
			else
			{
				int z = find(id);
				if (!z)
					cout << query(1, dfn[id], dfn[id] + siz[id]) << endl;
				else
				{
					int ans = query(1, 1, dfn[z]);
					if (dfn[z] + siz[z] < N + 1)
						ans = min(ans, query(1, dfn[z] + siz[z], N + 1));
					cout << ans << endl;
				}
			}
		}
	}
}

int main()
{
	IOS;
	cin >> N >> M;
	int u, v;
	for (int i = 1; i < N; i++)
		cin >> u >> v, add_edge(u, v);
	for (int i = 1; i <= N; i++)
		cin >> A[i];
	cin >> root;
	solve();

	return 0;
}

本文作者:Prgl

本文链接:https://www.cnblogs.com/Prgl/p/16457612.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Prgl  阅读(17)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开