zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    小div在大div中垂直居中方式
    sublime中Vue高亮插件安装
    vue脚手架创建项目(推荐)
    搭建Vue脚手架
    html解决空格显示问题
    css3实现半圆和圆效果
    MySQL通过 LOAD DATA INFILE 批量导入数据
    jQuery ajax 提交表单图片
    Sqlserver风格规范
    前端代码风格规范总结
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249756.html
Copyright © 2011-2022 走看看