• [BZOJ1984]月下“毛景树”解题报告|树链剖分


     

    Description

      毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:  Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。  Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:  Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
    树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:  Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。  Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:  Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
     
      这道题可讲之处显然都在线段树上了...
      事实证明现在的泪都是当年学线段树时脑子进的水...
     
      1 program bzoj1984;
      2 const maxn=100010;maxm=200010;
      3 var n,i,j,x,y,z,cnt,t:longint;
      4     ch:char;
      5     ter,next,w:array[-1..maxm]of longint;
      6     link,deep,size,v,son,pos,belong:array[-1..maxn]of longint;
      7     tr:array[-1..5*maxn]of record l,r,mx,add,c:longint;wait:boolean;end;
      8     fa:array[-1..maxn,-1..20]of longint;
      9 
     10 function max(a,b:longint):longint;
     11 begin
     12     if a>b then exit(a) else exit(b);
     13 end;
     14 
     15 procedure add(x,y,z:longint);
     16 begin
     17     inc(j);ter[j]:=y;next[j]:=link[x];link[x]:=j;w[j]:=z;
     18     inc(j);ter[j]:=x;next[j]:=link[y];link[y]:=j;w[j]:=z;
     19 end;
     20 
     21 procedure dfs1(p:longint);
     22 var i,j:longint;
     23 begin
     24     size[p]:=1;
     25     for i:=1 to 17 do
     26     begin
     27         if deep[p]<=1 << i then break;
     28         fa[p][i]:=fa[fa[p][i-1]][i-1];
     29     end;
     30     j:=link[p];
     31     while j<>0 do
     32     begin
     33         if deep[ter[j]]=0 then
     34         begin
     35             deep[ter[j]]:=deep[p]+1;
     36             fa[ter[j]][0]:=p;
     37             v[ter[j]]:=w[j];son[(j+1) >> 1]:=ter[j];
     38             dfs1(ter[j]);
     39             inc(size[p],size[ter[j]]);
     40         end;
     41         j:=next[j];
     42     end;
     43 end;
     44 
     45 procedure dfs2(p,chain:longint);
     46 var j,k:longint;
     47 begin
     48     inc(cnt);pos[p]:=cnt;belong[p]:=chain;
     49     k:=0;
     50     j:=link[p];
     51     while j<>0 do
     52     begin
     53         if deep[ter[j]]>deep[p] then
     54             if size[ter[j]]>size[k] then k:=ter[j];
     55         j:=next[j];
     56     end;
     57     if k=0 then exit;
     58     dfs2(k,chain);
     59     j:=link[p];
     60     while j<>0 do
     61     begin
     62         if deep[ter[j]]>deep[p] then
     63             if k<>ter[j] then dfs2(ter[j],ter[j]);
     64         j:=next[j];
     65     end;
     66 end;
     67 
     68 procedure build(p,l,r:longint);
     69 var mid:longint;
     70 begin
     71     tr[p].l:=l;tr[p].r:=r;tr[p].mx:=0;tr[p].wait:=false;tr[p].add:=0;
     72     if l=r then exit;
     73     mid:=(l+r) >> 1;
     74     build(p << 1,l,mid);
     75     build(p << 1+1,mid+1,r);
     76 end;
     77 
     78 procedure push(p:longint);
     79 begin
     80     if tr[p].l=tr[p].r then exit;
     81     if tr[p].wait then
     82     begin
     83         //与上一题不同,这一题并不存在下面的点在更新之后能比现在更好的情况所以不需要push(p << 1);push(p << 1+1)
     84         //否则会TLE
     85         tr[p << 1].add:=0;tr[p << 1+1].add:=0;
     86         //这两句很关键 因为当儿子节点再往下更新的时候如果add没有清零再往下的点会被赋上不等于tr[p].mx的值
     87         tr[p << 1].mx:=tr[p].mx;tr[p << 1].wait:=true;
     88         tr[p << 1+1].mx:=tr[p].mx;tr[p << 1+1].wait:=true;
     89         tr[p].wait:=false;
     90         tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
     91     end;
     92     if tr[p].add<>0 then
     93     begin
     94         inc(tr[p << 1].mx,tr[p].add);
     95         if not tr[p << 1].wait then inc(tr[p << 1].add,tr[p].add); 
     96         //这个特判很关键也很隐蔽 因为如果tr[p << 1].wait=True的话它往下传的时候应该把tr[p << 1].mx+tr[p].add传递下去
     97         //但是如果把tr[p << 1].add也加上了tr[p].add的话相当于重复相加 就出错了
     98         inc(tr[p << 1+1].mx,tr[p].add);
     99         if not tr[p << 1+1].wait then inc(tr[p << 1+1].add,tr[p].add);
    100         tr[p].add:=0;
    101         tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
    102     end;
    103 end;
    104 
    105 procedure insert(p,l,r,ave:longint);
    106 var mid:longint;
    107 begin
    108     push(p);
    109     if (tr[p].l=l)and(tr[p].r=r) then
    110     begin
    111         tr[p].mx:=ave;tr[p].wait:=true;
    112         exit;
    113     end;
    114     mid:=(tr[p].l+tr[p].r) >> 1;
    115     if r<=mid then insert(p << 1,l,r,ave) else
    116         if l>mid then insert(p << 1+1,l,r,ave) else
    117         begin
    118             insert(p << 1,l,mid,ave);
    119             insert(p << 1+1,mid+1,r,ave);
    120         end;
    121     tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
    122 end;
    123 
    124 function lca(x,y:longint):longint;
    125 var tem,i:longint;
    126 begin
    127     if deep[x]<deep[y] then
    128     begin
    129         tem:=x;x:=y;y:=tem;
    130     end;
    131     if deep[x]<>deep[y] then
    132     begin
    133         i:=trunc(ln(deep[x]-deep[y])/ln(2));
    134         while deep[x]>deep[y] do
    135         begin
    136             while (deep[x]-deep[y]>=1 << i) do x:=fa[x][i];
    137             dec(i);
    138         end;
    139     end;
    140     if x=y then exit(x);
    141     i:=trunc(ln(n)/ln(2));
    142     while fa[x][0]<>fa[y,0] do
    143     begin
    144         while fa[x,i]<>fa[y,i] do
    145         begin
    146             x:=fa[x,i];y:=fa[y,i];
    147         end;
    148         dec(i);
    149     end;
    150     exit(fa[x,0]);
    151 end;
    152 
    153 procedure add(p,l,r,ave:longint);
    154 var mid:longint;
    155 begin
    156     push(p);
    157     if (tr[p].l=l)and(tr[p].r=r) then
    158     begin
    159         inc(tr[p].mx,ave);
    160         inc(tr[p].add,ave);
    161         exit;
    162     end;
    163     mid:=(tr[p].l+tr[p].r) >> 1;
    164     if r<=mid then add(p << 1,l,r,ave) else
    165         if l>mid then add(p << 1+1,l,r,ave) else
    166         begin
    167             add(p << 1,l,mid,ave);
    168             add(p << 1+1,mid+1,r,ave);
    169         end;
    170     tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
    171 end;
    172 
    173 function query(p,l,r:longint):longint;
    174 var mid:longint;
    175 begin
    176     push(p);
    177     if (tr[p].l=l)and(tr[p].r=r) then exit(tr[p].mx);
    178     mid:=(tr[p].l+tr[p].r) >> 1;
    179     if r<=mid then exit(query(p << 1,l,r)) else
    180         if l>mid then exit(query(p << 1+1,l,r)) else
    181         exit(max(query(p << 1,l,mid),query(p << 1+1,mid+1,r)));
    182 end;
    183 
    184 procedure solve_change(x,y,z:longint);
    185 begin
    186     while belong[x]<>belong[y] do
    187     begin
    188         insert(1,pos[belong[x]],pos[x],z);
    189         x:=fa[belong[x]][0];
    190     end;
    191     if x<>y then insert(1,pos[y]+1,pos[x],z);
    192 end;
    193 
    194 procedure solve_add(x,y,z:longint);
    195 begin
    196     while belong[x]<>belong[y] do
    197     begin
    198         add(1,pos[belong[x]],pos[x],z);
    199         x:=fa[belong[x]][0];
    200     end;
    201     if x<>y then add(1,pos[y]+1,pos[x],z);
    202 end;
    203 
    204 function solve_mx(x,y:longint):longint;
    205 var sum:longint;
    206 begin
    207     sum:=0;
    208     while belong[x]<>belong[y] do
    209     begin
    210         sum:=max(sum,query(1,pos[belong[x]],pos[x]));
    211         x:=fa[belong[x]][0];
    212     end;
    213     if x<>y then sum:=max(sum,query(1,pos[y]+1,pos[x]));
    214     exit(sum);
    215 end;
    216 
    217 begin
    218     readln(n);
    219     j:=0;
    220     for i:=1 to n-1 do
    221     begin
    222         readln(x,y,z);
    223         add(x,y,z);
    224     end;
    225     deep[1]:=1;dfs1(1);
    226     cnt:=0;dfs2(1,1);
    227     build(1,1,n);
    228     for i:=1 to n do insert(1,pos[i],pos[i],v[i]);
    229     read(ch);
    230     while ch<>'S' do
    231     begin
    232         if ch='C' then
    233         begin
    234             read(ch);
    235             if ch='h' then
    236             begin
    237                 readln(ch,ch,ch,ch,x,y);
    238                 insert(1,pos[son[x]],pos[son[x]],y);
    239             end else
    240             begin
    241                 readln(ch,ch,ch,x,y,z);
    242                 t:=lca(x,y);
    243                 solve_change(x,t,z);solve_change(y,t,z);
    244             end;
    245         end else
    246         if ch='A' then
    247         begin
    248             readln(ch,ch,x,y,z);
    249             t:=lca(x,y);
    250             solve_add(x,t,z);solve_add(y,t,z);
    251         end else
    252         begin
    253             readln(ch,ch,x,y);
    254             t:=lca(x,y);
    255             writeln(max(solve_mx(x,t),solve_mx(y,t)));
    256         end;
    257         read(ch);
    258     end;
    259 end.
    260     
     
  • 相关阅读:
    基于thinkphp3.2.3开发的CMS内容管理系统(二)- Rbac用户权限
    phpstrom 快捷键
    基于thinkphp3.2.3开发的CMS内容管理系统
    html中的字幕滚动marquee属性
    学会这些网站优化技巧,秒变seo专家
    服务器设置防火墙规则,实现远程桌面连接的ip限制
    IIS7.5中神秘的ApplicationPoolIdentity
    mysql 安装成功后如何设置密码?
    网站优化提高加载速度的14个技巧
    解决帝国cms系统后台管理员登录密码输入五次密码错误后需等候60分钟的方法
  • 原文地址:https://www.cnblogs.com/mjy0724/p/4417743.html
Copyright © 2020-2023  润新知