正题
P3979
题目大意
给你一棵树,让你进行一下操作:
- 把根节点修改为x
- 把x到y路径上的点权值修改为v
- 查询x子树中的最小权值
解题思路
可以用LCT维护该树
查询时先make_root(rt)make\_root(rt)make_root(rt),然后把x旋转到rt的儿子,再计算虚子树部分即可
code
#include<set>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 100010
using namespace std;
int n,m,x,y,z,rt,top,tot,ans,h[N],D[N];
struct Tree
{#define ls son[x][0]#define rs son[x][1]int v[N],w[N],p[N],wl[N],wv[N],pc[N],fa[N],son[N][2];multiset<int>d[N];bool NR(int x){return fa[x]&&(son[fa[x]][0]==x||son[fa[x]][1]==x);}bool IRS(int x){return son[fa[x]][1]==x;}void pushr(int x){if(!x)return;swap(ls,rs);p[x]^=1;return;}void pushc(int x,int y){if(!x)return;wv[x]=v[x]=w[x]=y;w[x]=min(wl[x],wv[x]);pc[x]=1; return;}void push_down(int x){if(!x)return;if(pc[x]){if(ls)pushc(ls,v[x]);if(rs)pushc(rs,v[x]);pc[x]=0;}if(p[x]){if(ls)pushr(ls);if(rs)pushr(rs);p[x]=0; }return;}void push_up(int x){if(!x)return;wl[x]=min(wl[ls],wl[rs]);if(d[x].size())wl[x]=min(wl[x],*d[x].begin());wv[x]=min(v[x],min(wv[ls],wv[rs]));w[x]=min(wl[x],wv[x]);return;}void rotate(int x){int y=fa[x],z=fa[y],k=IRS(x),g=son[x][!k];if(NR(y))son[z][IRS(y)]=x;if(g)fa[g]=y;fa[y]=x;fa[x]=z;son[x][!k]=y;son[y][k]=g;push_up(y);return;}void Splay(int x){int y=x;D[++top]=y;while(NR(y))y=fa[y],D[++top]=y;while(top)push_down(D[top]),top--;while(NR(x)){if(NR(fa[x])){if(IRS(x)==IRS(fa[x]))rotate(fa[x]);else rotate(x);}rotate(x);}push_up(x);return;}void access(int x){for(int y=0;x;x=fa[y=x]){Splay(x);if(rs)d[x].insert(w[rs]);rs=y;if(rs)d[x].erase(d[x].find(w[rs]));push_up(x);}return;}void make_root(int x){access(x);Splay(x);pushr(x);return;}void link(int x,int y){fa[y]=x;d[x].insert(w[y]);return;}void Split(int x,int y){make_root(x);access(y);Splay(y);return;}
}T;
struct rec
{int to,nx;
}e[N<<1];
void add(int x,int y)
{e[++tot].to=y;e[tot].nx=h[x];h[x]=tot;return;
}
int read()
{char c=getchar();int ds=0,fs=1;while (c<'0'||'9'<c) {if (c=='-') fs=-1;c=getchar();}while (c>='0'&&c<='9') ds=(ds<<3)+(ds<<1)+c-48,c=getchar();return ds*fs;
}
void dfs(int x,int fa)
{for(int i=h[x];i;i=e[i].nx){int y=e[i].to;if(y!=fa){dfs(y,x);T.link(x,y);}}T.push_up(x);return;
}
int main()
{scanf("%d%d",&n,&m);T.v[0]=T.wl[0]=T.wv[0]=T.w[0]=2147483647;for(int i=1;i<n;++i){scanf("%d%d",&x,&y);add(x,y);add(y,x);}for(int i=1;i<=n;++i)T.v[i]=read();scanf("%d",&rt);dfs(rt,0);while(m--){x=read();if(x==1)scanf("%d",&rt);else if(x==2){scanf("%d%d%d",&x,&y,&z);T.Split(x,y);T.pushc(y,z);}else{scanf("%d",&x);T.make_root(rt);T.Split(rt,x);ans=T.v[x];if(T.d[x].size())ans=min(ans,*T.d[x].begin()); //Split中xaccess了,所以没有右子树printf("%d\n",ans);}}return 0;
}