P3979 遥远的国度
换根操作不用真的换根
发现只有子树操作有影响。
而且是修改的点是新根的祖先的时候有影响。
当前点往新根那个方向的子树都不能计算进去,其他全部计算即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<vector>
#include<set>
#include<iomanip>
#include<ctime>
#include<cstdlib>
#include<cmath>
#define int long long
using namespace std;
#define orz cout<<"lyakioi!!!!!!!!!!!!!!!!!"<<endl
inline int r(){int s=0,k=1;char c=getchar();while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}while(isdigit(c)){s=s*10+c-'0';c=getchar();}return s*k;}
int cnt,son[1000001],n,m,head[1000001],deep[1000001],fa[1000001],size[1000001],tr[1000001],la[1000001],id[1000001],w[1000001],nw[1000001],root,times,top[1000001];
struct node
{
int to,next;
}a[1000001];
void add_edge(int from,int to)
{
a[++cnt].to=to;
a[cnt].next=head[from];
head[from]=cnt;
}
void dfs1(int u,int father,int deeps)
{
deep[u]=deeps;
fa[u]=father;
size[u]=1;
int maxi=0;
for(int i=head[u];i;i=a[i].next)
{
int v=a[i].to;
if(v==father)continue;
dfs1(v,u,deeps+1);
size[u]+=size[v];
if(maxi<size[v])
{
son[u]=v;
maxi=size[v];
}
}
}
void dfs2(int u,int tp)
{
times++;
id[u]=times;
top[u]=tp;
nw[times]=w[u];
if(son[u])dfs2(son[u],tp);
for(int i=head[u];i;i=a[i].next)
{
int v=a[i].to;
if(!id[v])dfs2(v,v);
}
}
void push_down(int bh,int k)
{
tr[bh]=la[bh]=k;
}
void build(int l,int r,int bh)
{
if(l==r)
{
tr[bh]=nw[l];
return;
}
int mid=(l+r)/2;
build(l,mid,bh*2);
build(mid+1,r,bh*2+1);
tr[bh]=min(tr[bh*2],tr[bh*2+1]);
}
void tr_add(int now_l,int now_r,int bh,int l,int r,int k)
{
if(l<=now_l&&now_r<=r)
{
push_down(bh,k);
return;
}
if(now_l>r||now_r<l)return;
int mid=(now_l+now_r)/2;
if(la[bh])
{
push_down(bh*2,la[bh]);
push_down(bh*2+1,la[bh]);
la[bh]=0;
}
tr_add(now_l,mid,bh*2,l,r,k);
tr_add(mid+1,now_r,bh*2+1,l,r,k);
tr[bh]=min(tr[bh*2],tr[bh*2+1]);
}
int sum(int now_l,int now_r,int bh,int l,int r)
{
if(l<=now_l&&now_r<=r)return tr[bh];
if(now_l>r||now_r<l)return 1e18;
int mid=(now_l+now_r)/2;
if(la[bh])
{
push_down(bh*2,la[bh]);
push_down(bh*2+1,la[bh]);
la[bh]=0;
}
return min(sum(now_l,mid,bh*2,l,r),sum(mid+1,now_r,bh*2+1,l,r));
}
void add(int x,int y,int w)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
tr_add(1,n,1,id[top[x]],id[x],w);
x=top[x];x=fa[x];
}
if(deep[x]<deep[y])swap(x,y);
tr_add(1,n,1,id[y],id[x],w);
}
signed main()
{
int x,y,z,opt,newroot;
n=r();m=r();
for(int i=1;i<n;i++)
{
x=r();y=r();
add_edge(x,y);
add_edge(y,x);
}
for(int i=1;i<=n;i++)w[i]=r();
root=r();newroot=root;
dfs1(root,0,1);
dfs2(root,root);
// for(int i=1;i<=n;i++)cout<<"ah"<<nw[i]<<endl;
build(1,n,1);
// cout<<"??"<<tr[1]<<endl;
for(int i=1;i<=m;i++)
{
opt=r();
if(opt==1)newroot=r();
else if(opt==2)
{
x=r();y=r();z=r();
add(x,y,z);
}
else
{
int ans=0;
x=r();
if(x==newroot)ans=tr[1];
else if(id[x]<id[newroot]&&id[newroot]<=id[x]+size[x]-1)
{
for(int i=head[x];i;i=a[i].next)
{
int v=a[i].to;
if(v==fa[x])continue;
if(id[v]<=id[newroot]&&id[newroot]<=id[v]+size[v]-1)
{
ans=min(sum(1,n,1,1,id[v]-1),sum(1,n,1,id[v]+size[v],n));
break;
}
}
}
else ans=sum(1,n,1,id[x],id[x]+size[x]-1);
cout<<ans<<endl;
}
}
}
本文来自博客园,作者:lei_yu,转载请注明原文链接:https://www.cnblogs.com/lytql/p/15224577.html