只A了前两个点,#5还T了,求大佬帮我看看
#include<bits/stdc++.h>
using namespace std;
#define ls (now<<1)
#define rs (ls|1)
#define mid ((l+r)>>1)
const int N=100100,M=100100;
int n,m,rot=1,lit;
int a[N],id[N],nid[N],cnt[N],hea[N],dep[N],cap[N],fa[N];
int head[N],to[2*M],next[2*M],tot=0;
struct node{
int mn,tag;
}tre[4*N];
void add(int x,int y){
to[++tot]=y;
next[tot]=head[x];
head[x]=tot;
}
void dfs(int now){
int ord=0;
cnt[now]=1;//当前点有大小
for(int i=head[now];i;i=next[i]){
int nxt=to[i];
if(dep[nxt]) continue;
fa[nxt]=now;//标记上一结点
dep[nxt]=dep[now]+1;//更新层数
dfs(nxt);//深搜
cnt[now]+=cnt[nxt];//更新当前子树大小
if(cnt[nxt]>cnt[ord]) ord=nxt;//更新最大子树
}
hea[now]=ord;//最大子树
}
void fhea(int now,int Fa){
cap[nid[id[now]=++lit]=now]=Fa;//更新重链头、id、逆id
if(!hea[now]) return;//没有重后代即必为叶节点
fhea(hea[now],Fa);//优先重儿子,保证性质
for(int i=head[now];i;i=next[i]){
int nxt=to[i];
if(nxt==fa[now]||nxt==hea[now]) continue;//防止反向搜索
fhea(nxt,nxt);
}
return;
}
void pushup(int now){
tre[now].mn=min(!tre[ls].mn?0x3f3f3f3f:tre[ls].mn,!tre[rs].mn?0x3f3f3f3f:tre[rs].mn);
}
void pushdown(int now){
if(!tre[now].tag) return;
tre[ls].mn=tre[ls].tag=tre[rs].mn=tre[rs].tag=tre[now].tag;
tre[now].tag=0;
}
void build(int now,int l,int r){
if(l==r){
tre[now].mn=a[nid[l]];
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
pushup(now);
}
void fix(int now,int l,int r,int L,int R,int num){
if(L<=l&&r<=R){
tre[now].mn=tre[now].tag=num;
return;
}
pushdown(now);
if(L<=mid) fix(ls,l,mid,L,R,num);
if(R>mid) fix(rs,mid+1,r,L,R,num);
pushup(now);
}
void lik_fix(int fom,int to,int num){
while(cap[fom]!=cap[to]){
if(dep[cap[fom]]<dep[cap[to]]) swap(fom,to);
fix(1,1,n,id[cap[fom]],id[fom],num);
fom=fa[cap[fom]];
}
if(dep[fom]>dep[to]) swap(fom,to);
fix(1,1,n,id[fom],id[to],num);
}
int query(int now,int l,int r,int L,int R){
if(L>R) return 0x3f3f3f3f;
int ans=0x3f3f3f3f;
if(L<=l&&r<=R){
return tre[now].mn;
}
pushdown(now);
if(L<=mid) ans=min(ans,query(ls,l,mid,L,R));
if(R>mid) ans=min(ans,query(rs,mid+1,r,L,R));
pushup(now);
return ans;
}
int lca(int x,int y){
while(cap[x]!=cap[y]){
if(dep[cap[x]]<dep[cap[y]]) swap(x,y);
x=fa[cap[x]];
}
return dep[x]<dep[y]?x:y;
}
void rot_mn(int now,int nrot){
int rel=lca(now,nrot),lst;
if(now==nrot){
printf("%d\n",tre[1].mn);
return;
}
if(rel!=now){
printf("%d\n",query(1,1,n,id[now],id[now]+cnt[now]-1));
}
else{
int ans=0x3f3f3f3f;
lst=nrot;
while(fa[lst]!=now) if(dep[fa[cap[lst]]]>dep[now]) lst=fa[cap[lst]]; else lst=fa[lst];
// printf("%d\n",min(query(1,1,n,id[rot],id[lst]-1),query(1,1,n,id[lst]+cnt[lst],id[rot]+cnt[rot]-1)));//除了nrot所在子树外,将整棵树的最小值统计一次
ans=query(1,1,n,1,id[lst]-1);
// printf("%d %d %d adsffadsf\n",lst,nrot,now);
if(id[lst]+cnt[lst]-1!=n) ans=min(ans,query(1,1,n,id[lst]+cnt[lst],n));
printf("%d\n",ans);
/*now=lst;
do{
lst=now;
now=fa[now];
for(int i=head[now];i;i=next[i]){
int nxt=to[i];
if(nxt==lst||nxt==fa[now]) continue;
ans=min(ans,query(1,1,n,id[nxt],id[nxt]+cnt[nxt]-1));
}
ans=min(ans,query(1,1,n,id[now],id[now]));
}while(now!=rot);
printf("%d\n",ans);*/
}
}
void check(int now,int l,int r){
printf("%d %d %d\n",l,r,tre[now].mn);
if(l==r) return;
check(ls,l,mid);
check(rs,mid+1,r);
}
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int k,x,y,z,nrot;
scanf("%d%d",&n,&m);
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++){
scanf("%d",&a[i]);
}
scanf("%d",&nrot);//结点间的相对位置是不变的,相当于最开始有一次操作1
dep[rot]=1;fa[rot]=rot;dfs(rot);//建树加各种标记+统计
fhea(rot,rot);//建链
build(1,1,n);//线段树统计链
// check(1,1,n);
for(int i=1,j=0;i<=m;i++){
scanf("%d %d",&k,&x);
if(k==1){
nrot=x;
}
else if(k==2){
scanf("%d%d",&y,&z);
lik_fix(x,y,z);
}
else{
// printf("%d ",++j);
rot_mn(x,nrot);
}
}
}