遥远的国度 (【bzoj3306】树)

3 篇文章 0 订阅

问题 F: 遥远的国度

时间限制: 1 Sec   内存限制: 128 MB
提交: 60   解决: 18
[ 提交][ 状态][ 讨论版]

题目描述

描述
zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。

问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。

输入

第1行两个整数n m,代表城市个数和操作数。
第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。
第n+1行,有n个整数,代表所有点的初始防御值。
第n+2行一个整数 id,代表初始的首都为id。
第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数p1 p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数 id,代表询问以城市id为根的子树中的最小防御值。

输出


对于每个opt=3的操作,输出一行代表对应子树的最小点权值。

样例输入

3 7
1 2
1 3
1 2 3
1
3 1
2 1 1 6
3 1
2 2 2 5
3 1
2 3 3 4
3 1

样例输出

1
2
3
4
提示
对于20%的数据,n<=1000 m<=1000。
对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。
对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。
对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。
对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。
【bzoj3306】树
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#define V 100003
#define LL long long
//#define maxn
#define INF 0x7fffffff
using namespace std;
struct data
{
 int to,from,next;       
}Edge[V*10];
int L,R,L1,R1;
LL add[V*10];
int tot,head[V],n,siz[V],son[V],dep[V];
int top[V],tot1,ps[V*10];
LL mx[V*10];
LL id[V],g[V],b[20],f[V][50],v[V];
void addedge(int x,int y)
{ 
  ++tot;
  Edge[tot].from=x;
  Edge[tot].to=y; 
  Edge[tot].next=head[x];
  head[x]=tot;     
}
void dfs1(int x)
{
          for(int i=1;i<=20;i++)
          if(b[i]<=dep[x])
          f[x][i]=f[f[x][i-1]][i-1];
          int z;
          siz[x]=1;
          son[x]=0;
          for(int i=head[x];i!=-1;i=Edge[i].next)
          {
                 z=Edge[i].to;
                 if(z!=f[x][0])
                 {
                    f[z][0]=x;
                    dep[z]=dep[x]+1;
                    dfs1(z);
                    siz[x]+=siz[z];
                    if(siz[z]>siz[son[x]])
                    son[x]=z;
                 }     
          }
}
void dfs2(int x,int ss)
{
      int z;
      top[x]=ss;
      tot1++;
      g[x]=id[x]=tot1;
      ps[tot1]=x;
      if(son[x])
      dfs2(son[x],ss);
      else return ;
      g[x]=max(g[x],g[son[x]]);
      for(int i=head[x];i!=-1;i=Edge[i].next)
      {
            z=Edge[i].to;        
         if(z!=f[x][0]&&z!=son[x])
         {
           dfs2(z,z); 
           g[x]=max(g[x],g[z]);
         }     
       }
}




inline void pushdown(int x,int l,int mid,int r)
{
      if(add[x])
      {
            add[x*2]=add[x];
            add[x*2+1]=add[x];
            mx[x*2]=add[x];
            mx[x*2+1]=add[x];
            add[x]=0;          
      }       
}
void build(int rt,int l,int r)
{
       if(l==r)
       {
         mx[rt]=v[ps[l]];
         return ;         
       } 
       int mid=(l+r)/2;
       build(rt*2,l,mid);
       build(rt*2+1,mid+1,r);
       mx[rt]=min(mx[rt*2],mx[rt*2+1]);   
}
LL query(int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
      return mx[rt]; 
    }
    int mid=(l+r)/2;
    pushdown(rt,l,mid,r); 
    LL res=INF;
    if(L<=mid)res=min(res,query(l,mid,rt*2));
    if(R>mid)res=min(res,query(mid+1,r,rt*2+1));
    return res;
}
void U(LL tt,int rt,int l,int r)
{
      if(L<=l&&R>=r)
      {
        add[rt]=tt;
        mx[rt]=tt;  
        return ;    
      }  
      int mid=(l+r)/2;   
     pushdown(rt,l,mid,r);
     if(L<=mid)
     U(tt,rt*2,l,mid);
     if(R>mid)
     U(tt,rt*2+1,mid+1,r);
     mx[rt]=min(mx[rt*2],mx[rt*2+1]);
} 
inline void Q1(int x,int y,LL z)
{
         if(x==y)
         {
            L=R=id[x];
            return U(z,1,1,n);//id[x],id[x],
         }
       int fx=top[x],fy=top[y],res=0;
       while(fx!=fy)
       {
             if(dep[fx]<dep[fy])
             {
                swap(x,y);
                swap(fx,fy);               
             }        
             L=id[fx];
             R=id[x];     
             U(z,1,1,n);//id[fx],id[x],
             x=f[fx][0];fx=top[x];
       } 
       if(dep[x]>dep[y])
       swap(x,y);
       L=id[x];
       R=id[y];
       U(z,1,1,n);//id[x],id[y],
}
int sg;
LL ddd()
{
   
   memset(head,-1,sizeof(head));
    memset(mx,127,sizeof(mx));
  // freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
  //freopen("bbbbb.in","r",stdin);freopen("bbbbb.out","w",stdout);
    //cout<<mx[1]<<"  "<<INF<<endl;
     b[0]=1;
     for(int i=1;i<=21;i++)
      b[i]=b[i-1]<<1; 
      int m;
       int x,y;
       scanf("%d%d",&n,&m);
      // cin>>n>>m;
      for(int i=1;i<n;i++)
      {
         scanf("%d%d",&x,&y);
         addedge(x,y);
         addedge(y,x);     
      }
     // cout<<tot;
    
        for(int i=1;i<=n;i++)
        scanf("%lld",&v[i]);
         //cin>>v[i];
         int op;
         LL d,gf,z;          
         //cin>>sg; 
         scanf("%d",&sg);
          dfs1(sg);
          dfs2(sg,sg);
          build(1,1,n);// while(1);
          //int sf;
          for(int i=1;i<=m;i++)
              {
                      // cin>>op;
                      scanf("%d",&op);
                       if(op==1)
                       {
                         scanf("%d",&sg);      
                       }        
                       if(op==2)
                       {
                            //cin>>x>>y>>z;
                            scanf("%d%d%lld",&x,&y,&z);
                            Q1(x,y,z);       
                       }
                       if(op==3)
                       {
                          // cin>>x;
                          scanf("%d",&x);
                           if(x==sg)
                           {
                            L=1;
                            R=n;
                            //cout<<"  !!! ";
                            printf("%lld\n",query(1,n,1));         
                           }
                           else if(id[x]<=id[sg]&&g[x]>=g[sg])
                           {
                                y=sg;
                                d=dep[y]-dep[x]-1;
                                for(int i=0;i<=20;i++)
                                if(b[i]&d)
                                y=f[y][i];
                                L=1;
                                R=id[y]-1;
                                gf=INF;
                                gf=min(gf,query(1,n,1));
                                L=g[y]+1;
                                R=n;
                                gf=min(gf,query(1,n,1));
                                printf("%lld\n",gf);
                           }
                           else
                           {
                               L=id[x];
                               R=g[x]; 
                               printf("%lld\n",query(1,n,1));
                           }
                       }      
                       
              }
       return 0;    
    
}
LL ttt=ddd();
int main()
{ ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值