[bzoj3083]遥远的国度

如果没有换根操作,可以直接用树剖维护,考虑修改操作与根无关,所以只需要特殊处理查询操作。

对于查询操作,假设查询点为x,初始的根是1,实际的根是r,一共要分三种情况来考虑:1. 若lca(r,x)!=x或x=r,则直接对以x为根的子树查询即可;

2. lca(r,x)=x且x!=r,则对整棵树除了以son为根的子树查询(sonx的边儿子也是r的祖先)。

PS:如果不使用倍增,使用树剖找lca,那么关于son的寻找有一点复杂,需要分类讨论:1.当树剖xr之后最终的两点相同,则记录最后一次树剖的top即为son2.当两点不同,就是x的重儿子。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 #define N 100005
  5 #define mid (l+r>>1)
  6 #define L (k<<1)
  7 #define R (L+1)
  8 struct ji{
  9     int nex,to;
 10 }edge[N<<1];
 11 int E,n,m,x,y,r,p,head[N],fa[N],id[N],top[N],sz[N],ma[N],sh[N];
 12 ll z,f[N<<2],laz[N<<2];
 13 void add(int x,int y){
 14     edge[E].nex=head[x];
 15     edge[E].to=y;
 16     head[x]=E++;
 17 }
 18 void dfs(int k,int f,int s){
 19     fa[k]=f;
 20     sh[k]=s;
 21     sz[k]=1;
 22     for(int i=head[k];i!=-1;i=edge[i].nex)
 23         if (edge[i].to!=f){
 24             dfs(edge[i].to,k,s+1);
 25             sz[k]+=sz[edge[i].to];
 26             if (sz[edge[i].to]>sz[ma[k]])ma[k]=edge[i].to;
 27         }
 28 }
 29 void dfs2(int k,int t){
 30     id[k]=++x;
 31     top[k]=t;
 32     if (ma[k])dfs2(ma[k],t);
 33     for(int i=head[k];i!=-1;i=edge[i].nex)
 34         if ((edge[i].to!=fa[k])&&(edge[i].to!=ma[k]))dfs2(edge[i].to,edge[i].to);
 35 }
 36 void down(int k){
 37     if (laz[k]){
 38         laz[L]=f[L]=laz[R]=f[R]=laz[k];
 39         laz[k]=0;
 40     }
 41 }
 42 void update(int k,int l,int r,int x,int y,int z){
 43     if ((l>y)||(x>r))return;
 44     if ((x<=l)&&(r<=y)){
 45         f[k]=laz[k]=z;
 46         return;
 47     }
 48     down(k);
 49     update(L,l,mid,x,y,z);
 50     update(R,mid+1,r,x,y,z);
 51     f[k]=min(f[L],f[R]);
 52 }
 53 ll query(int k,int l,int r,int x,int y){
 54     if ((l>y)||(x>r))return 3LL*0x3f3f3f3f;
 55     if ((x<=l)&&(r<=y))return f[k];
 56     down(k);
 57     return min(query(L,l,mid,x,y),query(R,mid+1,r,x,y));
 58 }
 59 void update(int x,int y,int z){
 60     while (top[x]!=top[y]){
 61         if (sh[top[x]]<sh[top[y]])swap(x,y);
 62         update(1,1,n,id[top[x]],id[x],z);
 63         x=fa[top[x]];
 64     }
 65     if (sh[x]>sh[y])swap(x,y);
 66     update(1,1,n,id[x],id[y],z);
 67 }
 68 ll query(int x){
 69     if (x==r)return f[1];
 70     y=r;
 71     int p=x;
 72     while (top[x]!=top[y]){
 73         if (sh[top[x]]<sh[top[y]])swap(x,y);
 74         z=top[x];
 75         x=fa[top[x]];
 76     }
 77     if (sh[x]>sh[y])swap(x,y);
 78     if (x!=p)return query(1,1,n,id[p],id[p]+sz[p]-1);
 79     if (x!=y)z=ma[x];
 80     return min(query(1,1,n,1,id[z]-1),query(1,1,n,id[z]+sz[z],n));
 81 }
 82 int main(){
 83     scanf("%d%d",&n,&m);
 84     memset(head,-1,sizeof(head));
 85     for(int i=1;i<n;i++){
 86         scanf("%d%d",&x,&y);
 87         add(x,y);
 88         add(y,x);
 89     }
 90     dfs(1,0,0);
 91     x=0;
 92     dfs2(1,1);
 93     for(int i=1;i<=n;i++){
 94         scanf("%lld",&z);
 95         update(1,1,n,id[i],id[i],z);
 96     }
 97     scanf("%d",&r);
 98     for(int i=1;i<=m;i++){
 99         scanf("%d%d",&p,&x);
100         if (p==1)r=x;
101         if (p==3)printf("%lld\n",query(x));
102         if (p==2){
103             scanf("%d%lld",&y,&z);
104             update(x,y,z);
105         }
106     }
107 }
View Code

 

posted @ 2019-07-28 10:38  PYWBKTDA  阅读(99)  评论(0编辑  收藏  举报