zoukankan      html  css  js  c++  java
  • 「BZOJ3083」遥远的国度(树剖换根

    3083: 遥远的国度

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 4859  Solved: 1372
    [Submit][Status][Discuss]

    Description

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

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

    Input

    第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为根的子树中的最小防御值。

    Output


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

    Sample Input

    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

    Sample Output

    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。

    HINT

    Source

    zhonghaoxi提供

    题解

    我也是有B站账号的女人了!

    这道题除了换根以外就很板子了,——所以我们聊聊换根。

    首先在原根下建出一棵树,设当前的根为root。
    对于子树k的操作:
    1.root==k 那么对整棵树操作。
    2.lca(root,k)!=k 也就是说root对k并没有什么影响,直接操作k。
    3.lca(root,k)==k root在k的子树中,想象一下揪着一根毛拿起一顶假发......
    那么对整个树中,除了原根意义下 k的儿子中含root的那一股 以外,的整棵树操作。
    (也可以认为对整个树操作,然后对root那一股撤销操作

    其实,所谓的换根操作,并不是要你每次把树再重新建一遍(复杂度起飞

    而是考你分类讨论的能力QAQ

    ——

    然后,一定一定要注意边界啊!字母不要混用啊!QAQ

    以及 鉴于数据极接近maxint,不如直接longlong2333

      1 /**************************************************************
      2     Problem: 3083
      3     User: qwerta
      4     Language: C++
      5     Result: Accepted
      6     Time:5528 ms
      7     Memory:55532 kb
      8 ****************************************************************/
      9  
     10 #include<algorithm>
     11 #include<iostream>
     12 #include<cstdio>
     13 #include<cmath>
     14 using namespace std;
     15 #define R register
     16 const int MAXN=100007;
     17 struct emm{
     18     int e,f;
     19 }b[2*MAXN];
     20 int h[MAXN];
     21 int tot=0;
     22 void con(int u,int v)
     23 {
     24     b[++tot].f=h[u];
     25     h[u]=tot;
     26     b[tot].e=v;
     27     b[++tot].f=h[v];
     28     h[v]=tot;
     29     b[tot].e=u;
     30     return;
     31 }
     32 int d[MAXN],fa[MAXN],top[MAXN],siz[MAXN],z[MAXN];
     33 void dfs(int x)
     34 {
     35     siz[x]=1,top[x]=x;
     36     int mac=0,macc=-1;
     37     for(R int i=h[x];i;i=b[i].f)
     38     if(!d[b[i].e])
     39     {
     40         d[b[i].e]=d[x]+1;
     41         fa[b[i].e]=x;
     42         dfs(b[i].e);
     43         siz[x]+=siz[b[i].e];
     44         if(macc<siz[b[i].e]){mac=b[i].e,macc=siz[b[i].e];}
     45     }
     46     z[x]=mac;
     47     top[mac]=x;
     48     return;
     49 }
     50 int q[MAXN],dfn[MAXN];
     51 void dfss(int x)
     52 {
     53     q[++tot]=x;
     54     dfn[x]=tot;
     55     if(z[x])dfss(z[x]);
     56     for(R int i=h[x];i;i=b[i].f)
     57     if(d[b[i].e]==d[x]+1&&b[i].e!=z[x])
     58     dfss(b[i].e);
     59     return;
     60 }
     61 int val[MAXN];
     62 int fitop(int x)
     63 {
     64     if(top[x]==x)return x;
     65     return top[x]=fitop(top[x]);
     66 }
     67 struct ahh{
     68     int l,r,mid;
     69     long long v,laz;
     70 }a[16*MAXN];
     71 #define lz (i<<1)
     72 #define rz ((i<<1)|1)
     73 #define md a[i].mid
     74 void build(int i,int ll,int rr)
     75 {
     76     a[i].l=ll;
     77     a[i].r=rr;
     78     if(ll==rr){a[i].v=val[q[ll]];return;}
     79     md=(ll+rr)>>1;
     80     build(lz,ll,md);
     81     build(rz,md+1,rr);
     82     a[i].v=min(a[lz].v,a[rz].v);
     83     return;
     84 }
     85 int k;
     86 void pushtag(int i)//啰嗦的pushtag
     87 {
     88     if(!a[i].laz)return;
     89     a[i].v=a[i].laz;
     90     if(a[i].l!=a[i].r)
     91     {
     92         a[lz].v=a[lz].laz=a[i].laz;
     93         a[rz].v=a[rz].laz=a[i].laz;
     94     }
     95     a[i].laz=0;
     96     return;
     97 }
     98 void change(int i,int ll,int rr)
     99 {
    100     pushtag(i);//覆盖操作可不像累加有交换律啊!修改也要pushtagQAQ
    101     if(a[i].l==ll&&a[i].r==rr){a[i].v=a[i].laz=k;return;}
    102     if(rr<=md)change(lz,ll,rr);
    103     else if(md+1<=ll)change(rz,ll,rr);
    104     else {change(lz,ll,md);change(rz,md+1,rr);}
    105     a[i].v=min(a[lz].v,a[rz].v);//记得一路更新上去QAQ
    106     return;
    107 }
    108 long long ans;
    109 void find(int i,int ll,int rr)
    110 {
    111     pushtag(i);
    112     if(a[i].l==ll&&a[i].r==rr){ans=min(ans,a[i].v);return;}
    113     if(rr<=md)find(lz,ll,rr);
    114     else if(md+1<=ll)find(rz,ll,rr);
    115     else {find(lz,ll,md);find(rz,md+1,rr);}
    116     a[i].v=min(a[lz].v,a[rz].v);
    117     return;
    118 }
    119 int filca(int u,int v)
    120 {
    121     while(top[u]!=top[v])
    122     {
    123         if(d[top[u]]<d[top[v]])swap(u,v);
    124         u=fa[top[u]];
    125     }
    126     if(d[u]<d[v])swap(u,v);
    127     return v;
    128 }
    129 int main()
    130 {
    131     //freopen("a.in","r",stdin);
    132     int n,m;
    133     scanf("%d%d",&n,&m);
    134     for(R int i=1;i<n;++i)
    135     {
    136         int u,v;
    137         scanf("%d%d",&u,&v);
    138         con(u,v);
    139     }
    140     for(R int i=1;i<=n;++i)
    141     scanf("%d",&val[i]);
    142     int s;
    143     scanf("%d",&s);
    144     d[s]=1;
    145     dfs(s);
    146     tot=0;
    147     dfss(s);
    148     for(R int i=1;i<=n;++i)
    149     top[i]=fitop(i);
    150     build(1,1,n);
    151     int rot=s;
    152     for(R int ew=1;ew<=m;++ew)//顺手打i->疯狂WA
    153     {
    154         int opt;
    155         scanf("%d",&opt);
    156         if(opt==1)
    157         {
    158             int id;
    159             scanf("%d",&id);
    160             rot=id;
    161         }
    162         else if(opt==2)
    163         {
    164             int u,v;
    165             scanf("%d%d%d",&u,&v,&k);
    166             while(top[u]!=top[v])
    167             {
    168                 if(d[top[u]]<d[top[v]])swap(u,v);
    169                 change(1,dfn[top[u]],dfn[u]);
    170                 u=fa[top[u]];
    171             }
    172             if(d[u]<d[v])swap(u,v);
    173             change(1,dfn[v],dfn[u]);
    174         }
    175         else
    176         {
    177             int x;
    178             scanf("%d",&x);
    179             ans=999999999999;
    180             if(rot==x)
    181               find(1,dfn[s],dfn[s]+siz[s]-1);
    182             else
    183             {
    184                 int lca=filca(rot,x);
    185                 if(lca!=x)
    186                 find(1,dfn[x],dfn[x]+siz[x]-1);
    187                 else
    188                 {
    189                     for(R int i=h[x];i;i=b[i].f)
    190                     if(d[b[i].e]==d[x]+1)
    191                     {
    192                         if(dfn[b[i].e]<=dfn[rot]&&dfn[b[i].e]+siz[b[i].e]-1>=dfn[rot])
    193                         {
    194                             find(1,1,dfn[b[i].e]-1);
    195                             if(dfn[b[i].e]+siz[b[i].e]<=n)//不注意边界->疯狂RE
    196                             find(1,dfn[b[i].e]+siz[b[i].e],n);
    197                         }
    198                     }
    199                 }
    200             }
    201             printf("%lld
    ",ans);
    202         }
    203     }
    204     return 0;
    205 }
    206 

    把AC率丢到地上蹂躏.jpg

  • 相关阅读:
    LCA算法
    poj1364(差分约束系统)
    dij算法为什么不能处理负权,以及dij算法变种
    差分约束系统
    最短路专辑
    LightOJ1348 树链剖分
    FZU2082树链剖分
    HYSBZ1036 树链剖分
    poj3237 树链剖分 暴力
    poj2763 树链剖分(线段树)
  • 原文地址:https://www.cnblogs.com/qwerta/p/9656629.html
Copyright © 2011-2022 走看看