P3979 遥远的国度 题解

我不会告诉你我把min写成max然后到处求助的

solve

  • 观察题目,行了终于不是边权了
  • 树剖区间改查最小+换根
  • 一有换根就很费劲诶
  • 开始考虑换根
  • 如何简化呢,每次换显然不行,我们可以假定一个点为根剖树然后根据输入来做决策
  • 考虑三种情况
  1. 现在的根正好是查的根,直接输cout << query(1,1,n) << endl;
  2. 查的根不是现在的根的祖先,也是直接输就完了,给张图吧
    图1
  3. 查的根是现在的根的祖先,非常费劲,再分情况
    在同一个重链内,给图
    tu2
    令要找的根x的儿子为son,观察发现,可以把son及其子树搞出来,然后算剩的(?),其中son[x]需要找
    还有一种,再给图
    tu3
    和描述的不太一致呢
    发现,要求的是x所在的链头(?),即top[x]
  • 搞完了你讲清楚了吗
  • 注意:跳找son时不要换x,y不然要炸的喵

code

#include<bits/stdc++.h>
#define endl '\n'
#define Honkai ios::sync_with_stdio(0);
#define StarRail cin.tie(0);cout.tie(0);
#define lson (rt<<1)
#define rson (rt<<1|1)
using namespace std;
constexpr int maxn=1e6+10;
int n,m,a[maxn],root;
int fa[maxn],dep[maxn],siz[maxn],son[maxn],top[maxn];
int dfn[maxn],rnk[maxn],cnt;
struct _ {int l,r;long long minn=0x7fffffffffffffff;int lazy;}tree[maxn<<2];
int h[maxn],to[maxn],nxt[maxn],tot;
void add(int x,int y) {tot++;to[tot]=y;nxt[tot]=h[x];h[x]=tot;}
void dfs1(int x)
{
	son[x]=-1;siz[x]=1;
	for (int i=h[x];i;i=nxt[i])
	{
		int y=to[i];
		if (dep[y]) continue;
		dep[y]=dep[x]+1;
		fa[y]=x;
		dfs1(y);
		siz[x]+=siz[y];
		if (son[x] == -1 || siz[y]>siz[son[x]]) son[x]=y;
	}
}
void dfs2(int x,int t)
{
	top[x]=t;
	cnt++;
	dfn[x]=cnt;rnk[cnt]=x;
	if (son[x] == -1) return;
	dfs2(son[x],t);
	for (int i=h[x];i;i=nxt[i])
	{
		int y=to[i];
		if (y == son[x] || y == fa[x]) continue;
		dfs2(y,y);
	}
}
void pushup(int rt) {tree[rt].minn=min(tree[lson].minn,tree[rson].minn);}
void pushdown(int rt)
{
	if (tree[rt].lazy)
	{
		int lz=tree[rt].lazy;
		tree[rt].lazy=0;
		tree[lson].lazy=tree[rson].lazy=lz;
		tree[lson].minn=tree[rson].minn=lz;
	}
}
void build(int rt,int l,int r)
{
	tree[rt].l=l;tree[rt].r=r;
	if (l == r) {tree[rt].minn=a[rnk[l]];return;}
	int mid=(l+r) >> 1;
	build(lson,l,mid);build(rson,mid+1,r);
	pushup(rt);
}
void update(int rt,int l,int r,int val)
{
	if (l<=tree[rt].l && tree[rt].r<=r) {tree[rt].minn=tree[rt].lazy=val;return;}
	pushdown(rt);
	int mid=(tree[rt].l+tree[rt].r) >> 1;
	if (l<=mid) update(lson,l,r,val);
	if (r>mid) update(rson,l,r,val);
	pushup(rt);
}
long long query(int rt,int l,int r)
{
	if (l>r) return 0x7fffffffffffffff;
	long long res=0x7fffffffffffffff;
	if (l<=tree[rt].l && tree[rt].r<=r) return tree[rt].minn;
	pushdown(rt);
	int mid=(tree[rt].l+tree[rt].r) >> 1;
	if (l<=mid) res=min(res,query(lson,l,r));
	if (r>mid) res=min(res,query(rson,l,r));
	return res;
}
void add1(int x,int y,int val)
{
	while (top[x]!=top[y])
	{
		if (dep[top[x]]<dep[top[y]]) swap(x,y);
		update(1,dfn[top[x]],dfn[x],val);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	update(1,dfn[x],dfn[y],val);
}
int jump(int x,int y)
{
	while (top[y]!=top[x])
	{
		if (x == fa[top[y]]) return top[y];
		y=fa[top[y]];
	}
	return son[x];
}
int main()
{
//	freopen("P3979_5.in","r",stdin);
//	freopen("777.out","w",stdout);
	Honkai StarRail
	cin >> n >> m;
	for (int i=1;i<n;i++)
	{
		int x,y;
		cin >> x >> y;
		add(x,y);add(y,x);
	}
	for (int i=1;i<=n;i++) cin >> a[i];
	cin >> root;
	dep[1]=1;
	dfs1(1);dfs2(1,1);
	build(1,1,cnt);
	while (m--)
	{
		int op;
		cin >> op;
		if (op == 1) cin >> root;
		if (op == 2)
		{
			int x,y,z;
			cin >> x >> y >> z;
			add1(x,y,z);
		}
		if (op == 3)
		{
			int u;
			cin >> u;
			if (u == root) cout << query(1,1,n) << endl;
			else if (dfn[u]>dfn[root] || dfn[u]+siz[u]-1<dfn[root]) cout << query(1,dfn[u],dfn[u]+siz[u]-1) << endl;
			else
			{
				int k=jump(u,root);
				if (dfn[k]+siz[k]-1 == n) cout << query(1,1,dfn[k]-1) << endl;
				else cout << min(query(1,1,dfn[k]-1),query(1,dfn[k]+siz[k],n)) << endl;
			}
		}
	}
	return 0;
}

鸣谢

zyz
wang7979
怎么又是你俩

posted @ 2026-06-06 16:58  msjing  阅读(9)  评论(0)    收藏  举报