zoukankan      html  css  js  c++  java
  • bzoj1036 [ZJOI2008]树的统计Count(树链剖分)

    Description

      一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

    Input

      输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 
         对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

    Output

      对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

    Sample Input

    4
    1 2
    2 3
    4 1
    4 2 1 3
    12
    QMAX 3 4
    QMAX 3 3
    QMAX 3 2
    QMAX 2 3
    QSUM 3 4
    QSUM 2 1
    CHANGE 1 5
    QMAX 3 4
    CHANGE 3 6
    QMAX 3 4
    QMAX 2 4
    QSUM 3 4

    Sample Output

    4
    1
    2
    2
    10
    6
    5
    6
    5
    16
     
     
    没什么可说的,就是复习一下树链剖分模板。
    以前做过,那是还是用指针存树的,也是dfs的。
    现在写的是数组模拟邻接表,以及非递归的预处理。
    这个非递归预处理可以使子树和链都在一起,也可以只保证链在一起,这题没有子树操作,只要后者即可,但也写了下使子树在一起的代码。
    先是只保证链在一起的代码:
      1 program rrr(input,output);
      2 const
      3   inf=123456789;
      4 type
      5   treetype=record
      6      l,r,max,sum:longint;
      7   end;
      8   etype=record
      9      t,next:longint;
     10   end;
     11 var
     12   a:array[0..120012]of treetype;
     13   b,c,father,siz,son,ss,idx,head,q,dep:array[0..30030]of longint;
     14   e:array[0..60060]of etype;
     15   n,m,i,j,x,y,cnt,h,t,ans:longint;
     16   s:string;
     17 function max(a,b:longint):longint;
     18 begin
     19    if a>b then exit(a) else exit(b);
     20 end;
     21 procedure add(x,y:longint);
     22 begin
     23    inc(cnt);e[cnt].t:=y;e[cnt].next:=c[x];c[x]:=cnt;
     24 end;
     25 procedure work;
     26 begin
     27    j:=pos(' ',s);val(copy(s,1,j-1),x);delete(s,1,j);val(s,y);
     28 end;
     29 procedure prepare;
     30 begin
     31    h:=0;t:=1;q[1]:=1;father[1]:=0;dep[1]:=1;
     32    while h<t do
     33       begin
     34          inc(h);
     35          i:=c[q[h]];
     36          while i<>0 do
     37             begin
     38                if e[i].t<>father[q[h]] then
     39                   begin
     40                      father[e[i].t]:=q[h];dep[e[i].t]:=dep[q[h]]+1;
     41                      inc(t);q[t]:=e[i].t;
     42                   end;
     43                i:=e[i].next;
     44             end;
     45       end;
     46    fillchar(son,sizeof(son),0);fillchar(ss,sizeof(ss),0);
     47    for i:=1 to n do siz[i]:=1;
     48    for i:=n downto 2 do
     49       begin
     50          inc(siz[father[q[i]]],siz[q[i]]);
     51          if siz[q[i]]>ss[father[q[i]]] then
     52             begin ss[father[q[i]]]:=siz[q[i]];son[father[q[i]]]:=q[i]; end;
     53       end;
     54    cnt:=0;fillchar(idx,sizeof(idx),0);
     55    for i:=1 to n do
     56       if idx[q[i]]=0 then
     57          begin
     58             j:=q[i];
     59             while j<>0 do begin inc(cnt);idx[j]:=cnt;head[j]:=q[i];j:=son[j]; end;
     60          end;
     61 end;
     62 procedure build(k,l,r:longint);
     63 var
     64   mid,i:longint;
     65 begin
     66    a[k].l:=l;a[k].r:=r;
     67    if l=r then begin a[k].max:=b[l];a[k].sum:=b[l];exit; end;
     68    mid:=(l+r)>>1;i:=k+k;
     69    build(i,l,mid);
     70    build(i+1,mid+1,r);
     71    a[k].max:=max(a[i].max,a[i+1].max);
     72    a[k].sum:=a[i].sum+a[i+1].sum;
     73 end;
     74 procedure change(k,x,y:longint);
     75 var
     76   mid,i:longint;
     77 begin
     78    if a[k].l=a[k].r then begin a[k].sum:=y;a[k].max:=y;exit end;
     79    mid:=(a[k].l+a[k].r)>>1;i:=k+k;
     80    if x<=mid then change(i,x,y) else change(i+1,x,y);
     81    a[k].max:=max(a[i].max,a[i+1].max);
     82    a[k].sum:=a[i].sum+a[i+1].sum;
     83 end;
     84 function askmax(k,x,y:longint):longint;
     85 var
     86   mid,ans:longint;
     87 begin
     88    if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].max);
     89    mid:=(a[k].l+a[k].r)>>1;
     90    ans:=-inf;
     91    if x<=mid then ans:=askmax(k+k,x,y);
     92    if mid<y then ans:=max(ans,askmax(k+k+1,x,y));
     93    exit(ans);
     94 end;
     95 function asksum(k,x,y:longint):longint;
     96 var
     97   mid,ans:longint;
     98 begin
     99    if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].sum);
    100    mid:=(a[k].l+a[k].r)>>1;
    101    ans:=0;
    102    if x<=mid then ans:=asksum(k+k,x,y);
    103    if mid<y then ans:=ans+asksum(k+k+1,x,y);
    104    exit(ans);
    105 end;
    106 procedure qmax;
    107 begin
    108    ans:=-inf;
    109    while head[x]<>head[y] do
    110       if dep[head[x]]>dep[head[y]] then
    111          begin
    112             ans:=max(ans,askmax(1,idx[head[x]],idx[x]));
    113             x:=father[head[x]];
    114          end
    115       else begin
    116          ans:=max(ans,askmax(1,idx[head[y]],idx[y]));
    117          y:=father[head[y]];
    118       end;
    119    if dep[x]>dep[y] then ans:=max(ans,askmax(1,idx[y],idx[x]))
    120    else ans:=max(ans,askmax(1,idx[x],idx[y]));
    121 end;
    122 procedure qsum;
    123 begin
    124    ans:=0;
    125    while head[x]<>head[y] do
    126       if dep[head[x]]>dep[head[y]] then
    127          begin
    128             ans:=ans+asksum(1,idx[head[x]],idx[x]);
    129             x:=father[head[x]];
    130          end
    131       else begin
    132          ans:=ans+asksum(1,idx[head[y]],idx[y]);
    133          y:=father[head[y]];
    134       end;
    135    if dep[x]>dep[y] then ans:=ans+asksum(1,idx[y],idx[x])
    136    else ans:=ans+asksum(1,idx[x],idx[y]);
    137 end;
    138 begin
    139    assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output);
    140    readln(n);
    141    fillchar(c,sizeof(c),0);cnt:=0;
    142    for i:=1 to n-1 do begin readln(x,y);add(x,y);add(y,x); end;
    143    prepare;
    144    for i:=1 to n do read(b[idx[i]]);
    145    build(1,1,n);
    146    readln(m);
    147    for i:=1 to m do
    148       begin
    149          readln(s);
    150          if s[1]='C' then begin delete(s,1,7);work;change(1,idx[x],y); end
    151          else if s[2]='M' then begin delete(s,1,5);work;qmax;writeln(ans); end
    152          else begin delete(s,1,5);work;qsum;writeln(ans); end;
    153       end;
    154    close(input);close(output);
    155 end.

    然后是是子树也在一起的代码:

      1 program rrr(input,output);
      2 const
      3   inf=123456789;
      4 type
      5   treetype=record
      6      l,r,max,sum:longint;
      7   end;
      8   etype=record
      9      t,next:longint;
     10   end;
     11 var
     12   a:array[0..120012]of treetype;
     13   b,c,father,siz,son,ss,idx,head,q,dep,ot:array[0..30030]of longint;
     14   e:array[0..60060]of etype;
     15   n,m,i,j,x,y,cnt,h,t,ans:longint;
     16   s:string;
     17 function max(a,b:longint):longint;
     18 begin
     19    if a>b then exit(a) else exit(b);
     20 end;
     21 procedure add(x,y:longint);
     22 begin
     23    inc(cnt);e[cnt].t:=y;e[cnt].next:=c[x];c[x]:=cnt;
     24 end;
     25 procedure work;
     26 begin
     27    j:=pos(' ',s);val(copy(s,1,j-1),x);delete(s,1,j);val(s,y);
     28 end;
     29 procedure prepare;
     30 begin
     31    h:=0;t:=1;q[1]:=1;father[1]:=0;dep[1]:=1;
     32    while h<t do
     33       begin
     34          inc(h);
     35          i:=c[q[h]];
     36          while i<>0 do
     37             begin
     38                if e[i].t<>father[q[h]] then
     39                   begin
     40                      father[e[i].t]:=q[h];dep[e[i].t]:=dep[q[h]]+1;
     41                      inc(t);q[t]:=e[i].t;
     42                   end;
     43                i:=e[i].next;
     44             end;
     45       end;
     46    fillchar(son,sizeof(son),0);fillchar(ss,sizeof(ss),0);
     47    for i:=1 to n do siz[i]:=1;
     48    for i:=n downto 2 do
     49       begin
     50          inc(siz[father[q[i]]],siz[q[i]]);
     51          if siz[q[i]]>ss[father[q[i]]] then
     52             begin ss[father[q[i]]]:=siz[q[i]];son[father[q[i]]]:=q[i]; end;
     53       end;
     54    fillchar(idx,sizeof(idx),0);ot[0]:=0;
     55    for i:=1 to n do
     56       if idx[q[i]]=0 then
     57          begin
     58             cnt:=ot[father[q[i]]];j:=q[i];
     59             while j<>0 do
     60                begin
     61                   head[j]:=q[i];
     62                   inc(cnt);idx[j]:=cnt;
     63                   ot[j]:=cnt;inc(ot[father[j]],siz[j]);
     64                   j:=son[j];
     65                end;
     66          end;
     67 end;
     68 procedure build(k,l,r:longint);
     69 var
     70   mid,i:longint;
     71 begin
     72    a[k].l:=l;a[k].r:=r;
     73    if l=r then begin a[k].max:=b[l];a[k].sum:=b[l];exit; end;
     74    mid:=(l+r)>>1;i:=k+k;
     75    build(i,l,mid);
     76    build(i+1,mid+1,r);
     77    a[k].max:=max(a[i].max,a[i+1].max);
     78    a[k].sum:=a[i].sum+a[i+1].sum;
     79 end;
     80 procedure change(k,x,y:longint);
     81 var
     82   mid,i:longint;
     83 begin
     84    if a[k].l=a[k].r then begin a[k].sum:=y;a[k].max:=y;exit end;
     85    mid:=(a[k].l+a[k].r)>>1;i:=k+k;
     86    if x<=mid then change(i,x,y) else change(i+1,x,y);
     87    a[k].max:=max(a[i].max,a[i+1].max);
     88    a[k].sum:=a[i].sum+a[i+1].sum;
     89 end;
     90 function askmax(k,x,y:longint):longint;
     91 var
     92   mid,ans:longint;
     93 begin
     94    if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].max);
     95    mid:=(a[k].l+a[k].r)>>1;
     96    ans:=-inf;
     97    if x<=mid then ans:=askmax(k+k,x,y);
     98    if mid<y then ans:=max(ans,askmax(k+k+1,x,y));
     99    exit(ans);
    100 end;
    101 function asksum(k,x,y:longint):longint;
    102 var
    103   mid,ans:longint;
    104 begin
    105    if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].sum);
    106    mid:=(a[k].l+a[k].r)>>1;
    107    ans:=0;
    108    if x<=mid then ans:=asksum(k+k,x,y);
    109    if mid<y then ans:=ans+asksum(k+k+1,x,y);
    110    exit(ans);
    111 end;
    112 procedure qmax;
    113 begin
    114    ans:=-inf;
    115    while head[x]<>head[y] do
    116       if dep[head[x]]>dep[head[y]] then
    117          begin
    118             ans:=max(ans,askmax(1,idx[head[x]],idx[x]));
    119             x:=father[head[x]];
    120          end
    121       else begin
    122          ans:=max(ans,askmax(1,idx[head[y]],idx[y]));
    123          y:=father[head[y]];
    124       end;
    125    if dep[x]>dep[y] then ans:=max(ans,askmax(1,idx[y],idx[x]))
    126    else ans:=max(ans,askmax(1,idx[x],idx[y]));
    127 end;
    128 procedure qsum;
    129 begin
    130    ans:=0;
    131    while head[x]<>head[y] do
    132       if dep[head[x]]>dep[head[y]] then
    133          begin
    134             ans:=ans+asksum(1,idx[head[x]],idx[x]);
    135             x:=father[head[x]];
    136          end
    137       else begin
    138          ans:=ans+asksum(1,idx[head[y]],idx[y]);
    139          y:=father[head[y]];
    140       end;
    141    if dep[x]>dep[y] then ans:=ans+asksum(1,idx[y],idx[x])
    142    else ans:=ans+asksum(1,idx[x],idx[y]);
    143 end;
    144 begin
    145    assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output);
    146    readln(n);
    147    fillchar(c,sizeof(c),0);cnt:=0;
    148    for i:=1 to n-1 do begin readln(x,y);add(x,y);add(y,x); end;
    149    prepare;
    150    for i:=1 to n do read(b[idx[i]]);
    151    build(1,1,n);
    152    readln(m);
    153    for i:=1 to m do
    154       begin
    155          readln(s);
    156          if s[1]='C' then begin delete(s,1,7);work;change(1,idx[x],y); end
    157          else if s[2]='M' then begin delete(s,1,5);work;qmax;writeln(ans); end
    158          else begin delete(s,1,5);work;qsum;writeln(ans); end;
    159       end;
    160    close(input);close(output);
    161 end.

    其实大部分都是一模一样的,只是预处理不一样。

  • 相关阅读:
    剑指offer 31.时间效率 整数中1出现的次数(从1到n整数中1出现的次数)
    剑指offer 30.时间效率 连续子数组的最大和
    ElasticSearch 数据路由原理+增删改查内部原理+写一致性原理以及quorum机制
    剑指offer 29.时间效率 最小的K个数
    剑指offer 28.时间效率 数组中出现次数超过一半的数字
    剑指offer 27.分解让复杂问题简单 字符串的排列
    ElasticSearch 并发冲突+悲观锁与乐观锁+基于_version和external version进行乐观锁并发控制
    剑指offer 26.分解让复杂问题简单 二叉搜索树与双向链表
    Spfa+DP【p2149】[SDOI2009]Elaxia的路线
    Dfs【bzoj3252】攻略
  • 原文地址:https://www.cnblogs.com/Currier/p/6642442.html
Copyright © 2011-2022 走看看