zoukankan      html  css  js  c++  java
  • 洛谷 3979 BZOJ 3083 遥远的国度

    【题解】

      这道题除去根操作就是普通的树链剖分了。但是有换根操作怎么处理呢?

      我们可以发现如果现在的根不在查询的点的子树里,那么对本次查询没有影响。如果现在的跟在查询的点x的子树里,那么答案将变为整棵树除去现在的根root所属的x的孩子的子树。

      为了快速确定root属于x的哪一个孩子,我们可以写个倍增。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cmath>
      5 #define N 200010
      6 #define LL long long
      7 #define rg register
      8 #define ls (u<<1)
      9 #define rs (u<<1|1)
     10 #define mid ((a[u].l+a[u].r)>>1)
     11 using namespace std;
     12 int n,m,tot,cnt,root=1,last[N],dep[N],siz[N],top[N],fa[N],hvy[N],dfn[N],pos[N],v[N],p[N][20];
     13 struct edge{
     14     int to,pre;
     15 }e[N<<1];
     16 struct tree{
     17     int l,r,mn,num; bool mark;
     18 }a[N<<2];
     19 inline int read(){
     20     int k=0,f=1; char c=getchar();
     21     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
     22     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
     23     return k*f;
     24 }
     25 void find(int u,int f){
     26     p[u][0]=f;
     27     for (int i=1;i<=log2(dep[u]);i++) p[u][i]=p[p[u][i-1]][i-1];
     28     for (int i=last[u],to=e[i].to;i;i=e[i].pre,to=e[i].to)
     29     if(to!=f) find(to,u);
     30 }
     31 void dfs1(int x){
     32     siz[x]=1; dep[x]=dep[fa[x]]+1;
     33     for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa[x]){
     34         fa[to]=x; dfs1(to); siz[x]+=siz[to];
     35         if(siz[x]>siz[hvy[x]]) hvy[x]=to;
     36     }
     37 }
     38 void dfs2(int x,int tp){
     39     top[x]=tp; dfn[x]=++cnt; pos[cnt]=x;
     40     if(hvy[x]) dfs2(hvy[x],tp);
     41     for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa[x]&&to!=hvy[x]) 
     42         dfs2(to,to);
     43 }
     44 void build(int u,int l,int r){
     45     a[u].l=l; a[u].r=r;
     46     if(l<r) build(ls,l,mid),build(rs,mid+1,r),a[u].mn=min(a[ls].mn,a[rs].mn);
     47     else a[u].mn=v[pos[l]];
     48 }
     49 inline void pushdown(int u){
     50     a[u].mark=0; a[ls].mark=a[rs].mark=1;
     51     a[ls].num=a[rs].num=a[u].num;
     52     a[ls].mn=a[rs].mn=a[u].mn;
     53 }
     54 void update(int u,int l,int r,int d){
     55     if(l<=a[u].l&&a[u].r<=r){
     56         a[u].mark=1; a[u].num=d; a[u].mn=d;
     57         return;
     58     }
     59     if(a[u].mark) pushdown(u);
     60     if(l<=mid) update(ls,l,r,d);
     61     if(r>mid) update(rs,l,r,d);
     62     a[u].mn=min(a[ls].mn,a[rs].mn);
     63 }
     64 int query(int u,int l,int r){
     65     if(l<=a[u].l&&a[u].r<=r) return a[u].mn;
     66     if(a[u].mark) pushdown(u); int ret=2e9;
     67     if(l<=mid) ret=min(ret,query(ls,l,r));
     68     if(r>mid) ret=min(ret,query(rs,l,r));
     69     return ret;
     70 }
     71 int main(){
     72     n=read(); m=read();
     73     for(rg int i=1;i<n;i++){
     74         int u=read(),v=read();
     75         e[++tot]=(edge){v,last[u]}; last[u]=tot;
     76         e[++tot]=(edge){u,last[v]}; last[v]=tot;
     77     }
     78     for(rg int i=1;i<=n;i++) v[i]=read();
     79     root=read();
     80     dfs1(root); dfs2(root,root); build(1,1,n); find(root,0);
     81     while(m--){
     82         int opt=read();
     83         if(opt==1) root=read();
     84         else if(opt==2){
     85             int x=read(),y=read(),d=read(),t1=top[x],t2=top[y];
     86             while(t1!=t2){
     87                 if(dep[t1]<dep[t2]) swap(t1,t2),swap(x,y);
     88                 update(1,dfn[t1],dfn[x],d);
     89                 x=fa[t1]; t1=top[x];
     90             }
     91             if(dep[x]>dep[y]) swap(x,y); 
     92             update(1,dfn[x],dfn[y],d);
     93         }
     94         else if(opt==3){
     95             int x=read();
     96             if(dfn[x]<dfn[root]&&dfn[root]<=dfn[x]+siz[x]-1){
     97                 int y=root;
     98                 for(int i=log2(dep[y]-dep[x]);i>=0&&(dep[x]+1)!=dep[y];i--)
     99                     if(dep[p[y][i]]>=dep[x]+1) y=p[y][i];
    100                 int ans=2e9;
    101                 ans=min(ans,query(1,1,dfn[y]-1));
    102                 ans=min(ans,query(1,dfn[y]+siz[y],n));
    103                 printf("%d
    ",ans);
    104             }
    105             else{
    106                 if(x==root) printf("%d
    ",query(1,1,n));
    107                 else printf("%d
    ",query(1,dfn[x],dfn[x]+siz[x]-1));
    108             }
    109         }
    110     }
    111     return 0;
    112 }
    View Code
  • 相关阅读:
    Log4Net 全方位跟踪程序运行
    ASP.NET MVC 3和Razor中的@helper 语法
    C# 4.0四大新特性代码示例与解读
    程序员必读
    重学算法(1)--遍历二叉树
    重学算法-目录
    Epplus使用技巧
    JQuery 获取URL中传递的参数
    Epplus 使用案例
    .net调用存储过程详解(转载)
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9405011.html
Copyright © 2011-2022 走看看