zoukankan      html  css  js  c++  java
  • [POJ3237]Tree解题报告|树链剖分|边剖

    关于边剖

      之前做的大多是点剖,其实转换到边剖非常简单。

      我的做法是每个点的点权记录其到父亲节点的边的边权。

      只要solve的时候不要把最上面的点记录在内就可以了。


    Tree

    Description

      You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

    CHANGE i v Change the weight of the ith edge to v
    NEGATE a b Negate the weight of every edge on the path from a to b
    QUERY a b Find the maximum weight of edges on the path from a to b

     

      这道题除了边剖之外另一个难点是处理NEGATE操作

      将从a到b路径上的边权都取反

      其实思考一下便知只要存mx和mn两个值然后反转的时候互换并取反就可以了

      但是出现了问题,我以前用的向下传递不对了

      因为反转操作的存在,当前的值很可能被子节点中本来并不优秀但是反转了之后能比当前点更好的点取代

      然而传统的情况下当(tr[p].l=l)and(tr[p].r=r)的时候就停止了

      这就导致了可能当前的状态并不是最优秀的

      我们用一个push操作先向下传递一遍并刷新当前的值

      保证当前p节点里的值都是真实存在的

      在每个过程里都先执行一次push操作

      时间复杂度看上去或许并不乐观,但是实际上标记为真的个数并不多

      像这样特殊的操作就需要这种保证正确性的传递方式

      以后遇到类似的题要多加思考

      (树链剖分的题代码量真的很大啊QAQ

      1 program poj3237;
      2 const maxn=10010;maxm=20010;
      3 var test,t,x,y,z,cnt,tt,n,m,j,i:longint;
      4     son,size,link,belong,deep,v,pos:array[-1..maxn]of longint;
      5     ter,next,w:array[-1..maxm]of longint;
      6     fa:array[-1..maxn,-1..20]of longint;
      7     tr:array[-1..5*maxn]of record l,r,mx,mi:longint;wait,op:boolean;end;
      8     ch:char;
      9 
     10 function max(a,b:longint):longint;
     11 begin
     12     if a>b then exit(a) else exit(b);
     13 end;
     14 
     15 function min(a,b:longint):longint;
     16 begin
     17     if a<b then exit(a) else exit(b);
     18 end;
     19 
     20 procedure add(x,y,z:longint);
     21 begin
     22     inc(j);ter[j]:=y;next[j]:=link[x];link[x]:=j;w[j]:=z;
     23     inc(j);ter[j]:=x;next[j]:=link[y];link[y]:=j;w[j]:=z;
     24 end;
     25 
     26 procedure dfs1(p:longint);
     27 var i,j:longint;
     28 begin
     29     size[p]:=1;
     30     for i:=1 to 15 do
     31     begin
     32         if deep[p]<=1 << i then break;
     33         fa[p][i]:=fa[fa[p][i-1]][i-1];
     34     end;
     35     j:=link[p];
     36     while j<>0 do
     37     begin
     38         if deep[ter[j]]=0 then
     39         begin
     40             deep[ter[j]]:=deep[p]+1;
     41             fa[ter[j]][0]:=p;
     42             v[ter[j]]:=w[j];son[(j+1) >> 1]:=ter[j];
     43             dfs1(ter[j]);
     44             inc(size[p],size[ter[j]]);
     45         end;
     46         j:=next[j];
     47     end;
     48 end;
     49 
     50 procedure dfs2(p,chain:longint);
     51 var j,k:longint;
     52 begin
     53     inc(cnt);pos[p]:=cnt;belong[p]:=chain;
     54     k:=0;
     55     j:=link[p];
     56     while j<>0 do
     57     begin
     58         if deep[ter[j]]>deep[p] then
     59             if size[ter[j]]>size[k] then k:=ter[j];
     60         j:=next[j];
     61     end;
     62     if k=0 then exit;
     63     dfs2(k,chain);
     64     j:=link[p];
     65     while j<>0 do
     66     begin
     67         if (deep[ter[j]]>deep[p])and(ter[j]<>k) then dfs2(ter[j],ter[j]);
     68         j:=next[j];
     69     end;
     70 end;
     71 
     72 procedure build(p,l,r:longint);
     73 var mid:longint;
     74 begin
     75     tr[p].l:=l;tr[p].r:=r;tr[p].mx:=-maxlongint;tr[p].mi:=maxlongint;tr[p].wait:=false;tr[p].op:=false;
     76     if l=r then exit;
     77     mid:=(l+r) >> 1;
     78     build(p << 1,l,mid);
     79     build(p << 1+1,mid+1,r);
     80 end;
     81 
     82 procedure push(p:longint);
     83 var tem:longint;
     84 begin
     85     if tr[p].l=tr[p].r then exit;
     86     if tr[p].wait then
     87     begin
     88         push(p << 1);push(p << 1+1);
     89         tr[p << 1].mx:=max(tr[p].mx,tr[p << 1].mx);tr[p << 1].mi:=min(tr[p << 1].mi,tr[p].mi);tr[p << 1].wait:=true;
     90         tr[p << 1+1].mx:=max(tr[p].mx,tr[p << 1+1].mx);tr[p << 1+1].mi:=min(tr[p << 1+1].mi,tr[p].mi);tr[p << 1+1].wait:=true;
     91         tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
     92         tr[p].mi:=min(tr[p << 1].mi,tr[p << 1+1].mi);
     93         tr[p].wait:=false;
     94     end;
     95     if tr[p].op then
     96     begin
     97         push(p << 1);push(p << 1+1);
     98         tem:=tr[p << 1].mx;tr[p << 1].mx:=-tr[p << 1].mi;tr[p << 1].mi:=-tem;tr[p << 1].op:=true;
     99         tem:=tr[p << 1+1].mx;tr[p << 1+1].mx:=-tr[p << 1+1].mi;tr[p << 1+1].mi:=-tem;tr[p << 1+1].op:=true;
    100         tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
    101         tr[p].mi:=min(tr[p << 1].mi,tr[p << 1+1].mi);
    102         tr[p].op:=false;
    103     end;
    104 end;
    105 
    106 procedure insert(p,l,r,ave:longint);
    107 var mid,tem:longint;
    108 begin
    109     push(p);
    110     if (tr[p].l=l)and(tr[p].r=r) then
    111     begin
    112         tr[p].mx:=ave;
    113         tr[p].mi:=ave;
    114         tr[p].wait:=true;
    115         exit;
    116     end;
    117     mid:=(tr[p].l+tr[p].r) >> 1;    
    118     if r<=mid then insert(p << 1,l,r,ave) else
    119         if l>mid then insert(p << 1+1,l,r,ave) else
    120         begin
    121             insert(p << 1,l,mid,ave);
    122             insert(p << 1+1,mid+1,r,ave);
    123         end;
    124     tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
    125     tr[p].mi:=min(tr[p << 1].mi,tr[p << 1+1].mi);
    126 end;
    127 
    128 function lca(x,y:longint):longint;
    129 var tem,i:longint;
    130 begin
    131     if deep[x]<deep[y] then
    132     begin
    133         tem:=x;x:=y;y:=tem;
    134     end;
    135     if deep[x]<>deep[y] then
    136     begin
    137         i:=trunc(ln(deep[x]-deep[y])/ln(2));
    138         while deep[x]>deep[y] do
    139         begin
    140             while deep[x]-deep[y]>=1 << i do x:=fa[x][i];
    141             dec(i);
    142         end;
    143     end;
    144     if x=y then exit(x);
    145     i:=trunc(ln(n)/ln(2));
    146     while fa[x][0]<>fa[y][0] do
    147     begin
    148         while fa[x][i]<>fa[y][i] do
    149         begin
    150             x:=fa[x][i];y:=fa[y][i];
    151         end;
    152         dec(i);
    153     end;
    154     exit(fa[x][0]);
    155 end;
    156 
    157 function query(p,l,r:longint):longint;
    158 var mid,tem:longint;
    159 begin
    160     push(p);
    161     if (tr[p].l=l)and(tr[p].r=r) then exit(tr[p].mx);    
    162     mid:=(tr[p].l+tr[p].r) >> 1;
    163     if r<=mid then exit(query(p << 1,l,r)) else
    164         if l>mid then exit(query(p << 1+1,l,r)) else
    165         exit(max(query(p << 1,l,mid),query(p << 1+1,mid+1,r)));
    166 end;
    167 
    168 procedure dop(p,l,r:longint);
    169 var mid,tem:longint;
    170 begin
    171     push(p);
    172     if (tr[p].l=l)and(tr[p].r=r) then
    173     begin
    174         tem:=tr[p].mx;tr[p].mx:=-tr[p].mi;tr[p].mi:=-tem;
    175         tr[p].op:=true;
    176         exit;
    177     end;
    178     mid:=(tr[p].l+tr[p].r) >> 1;
    179     if r<=mid then dop(p << 1,l,r) else
    180         if l>mid then dop(p << 1+1,l,r) else
    181         begin
    182             dop(p << 1,l,mid);
    183             dop(p << 1+1,mid+1,r);
    184         end;
    185     tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx);
    186     tr[p].mi:=min(tr[p << 1].mi,tr[p << 1+1].mi);
    187 end;
    188 
    189 function solve(x,y:longint):longint;
    190 var mx:longint;
    191 begin
    192     mx:=-maxlongint;
    193     while belong[x]<>belong[y] do
    194     begin
    195         mx:=max(mx,query(1,pos[belong[x]],pos[x]));
    196         x:=fa[belong[x]][0];
    197     end;
    198     if x<>y then mx:=max(mx,query(1,pos[y]+1,pos[x]));
    199     exit(mx);
    200 end;
    201 
    202 procedure mend(x,y:longint);
    203 begin
    204     while belong[x]<>belong[y] do
    205     begin
    206         dop(1,pos[belong[x]],pos[x]);
    207         x:=fa[belong[x]][0];
    208     end;
    209     if x<>y then dop(1,pos[y]+1,pos[x]);
    210 end;
    211 
    212 begin
    213     readln(test);
    214     for tt:=1 to test do
    215     begin
    216         readln;
    217         readln(n);j:=0;
    218         fillchar(link,sizeof(link),0);
    219         fillchar(next,sizeof(next),0);
    220         fillchar(deep,sizeof(deep),0);
    221         fillchar(fa,sizeof(fa),0);
    222         for i:=1 to n-1 do
    223         begin
    224             readln(x,y,z);
    225             add(x,y,z);
    226         end;
    227         deep[1]:=1;dfs1(1);
    228         cnt:=0;dfs2(1,1);
    229         build(1,1,n);
    230         for i:=1 to n do insert(1,pos[i],pos[i],v[i]);
    231         read(ch);
    232         while ch<>'D' do
    233         begin
    234             if ch='Q' then
    235             begin
    236                 readln(ch,ch,ch,ch,x,y);
    237                 t:=lca(x,y);
    238                 writeln(max(solve(x,t),solve(y,t)));
    239             end else
    240             if ch='N' then
    241             begin
    242                 readln(ch,ch,ch,ch,ch,x,y);
    243                 t:=lca(x,y);
    244                 mend(x,t);mend(y,t);
    245             end else
    246             begin
    247                 readln(ch,ch,ch,ch,ch,x,y);
    248                 insert(1,pos[son[x]],pos[son[x]],y);
    249             end;
    250             read(ch);
    251         end;
    252         readln;
    253     end;
    254 end.
  • 相关阅读:
    linux 解压命令
    在xampp集成环境下使用 thinkphp 连接oracle
    输入框实现新闻列表分页显示(一)
    MyEclipse获取注册码
    Oracle数据库创建表空间
    SQL Server之存储过程
    连接Oracle数据库帮助类
    Oracle数据库的导入和导出
    创建dml触发器
    java连接数据库步骤
  • 原文地址:https://www.cnblogs.com/mjy0724/p/4417212.html
Copyright © 2011-2022 走看看