• 【BZOJ3626】LCA(树上差分,树链剖分)


    题意:给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
    设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
    有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
    (即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

    n<=50000

    思路:From THU爷 LYY

    我们考虑这样一种暴力:

    对于dep[lca(i,j)],可以将0~i路径上的点的权值+1,那么答案就是0~j路径上的点的权值之和。

    因此对于[l,r]区间,可以将每个点到根节点的权值+1,那么答案ans[l,r]就是0~z路径上的点的权值之和。

    显然ans[l,r]=ans[1,r]-ans[1,l-1]。

    那么可以树链剖分,然后将0~n-1这n个点插入线段树中,顺便求出答案,复杂度O(nlogn^2)。

      1 const mo=201314;
      2 var t:array[0..500000]of record
      3                           a,s,l:longint;
      4                          end;
      5     head,vet,next,head1,vet1,next1,c,d,
      6     size,son,tid,id,top,flag,dep,fa,ans:array[0..150000]of longint;
      7     n,q,i,j,l,r,z,tot,f,v,time,e:longint;
      8 
      9 
     10 procedure add(a,b:longint);
     11 begin
     12  inc(tot);
     13  next[tot]:=head[a];
     14  vet[tot]:=b;
     15  head[a]:=tot;
     16 end;
     17 
     18 procedure swap(var x,y:longint);
     19 var t:longint;
     20 begin
     21  t:=x; x:=y; y:=t;
     22 end;
     23 
     24 procedure addq(a,b,c1,d1:longint);
     25 begin
     26  inc(tot);
     27  next1[tot]:=head1[a];
     28  vet1[tot]:=b;
     29  c[tot]:=c1;
     30  d[tot]:=d1;
     31  head1[a]:=tot;
     32 end;
     33 
     34 procedure dfs1(u:longint);
     35 var e,v,maxsize,t:longint;
     36 begin
     37  flag[u]:=1; size[u]:=1; son[u]:=0; t:=0;
     38  e:=head[u];
     39  while e<>0 do
     40  begin
     41   v:=vet[e];
     42   if flag[v]=0 then
     43   begin
     44    dep[v]:=dep[u]+1;
     45    dfs1(v);
     46    size[u]:=size[u]+size[v];
     47    if size[v]>t then
     48    begin
     49     t:=size[v]; son[u]:=v;
     50    end;
     51    e:=next[e];
     52   end;
     53  end;
     54 end;
     55 
     56 procedure dfs2(u,ance:longint);
     57 var e,v:longint;
     58 begin
     59  flag[u]:=1; inc(time); tid[u]:=time; id[time]:=u; top[u]:=ance;
     60  if son[u]>0 then dfs2(son[u],ance);
     61  e:=head[u];
     62  while e<>0 do
     63  begin
     64   v:=vet[e];
     65   if flag[v]=0 then dfs2(v,v);
     66   e:=next[e];
     67  end;
     68 end;
     69 
     70 procedure hash(var x:longint);
     71 begin
     72  if x>=mo then x:=x mod mo;
     73 end;
     74 procedure pushdown(x:longint);
     75 var l,r,tmp:longint;
     76 begin
     77  tmp:=t[x].a;
     78  if tmp=0 then exit;
     79  l:=x<<1; r:=l+1;
     80  t[l].a:=t[l].a+tmp; hash(t[l].a);
     81  t[r].a:=t[r].a+tmp; hash(t[r].a);
     82  t[l].s:=t[l].s+t[l].l*tmp; hash(t[l].s);
     83  t[r].s:=t[r].s+t[r].l*tmp; hash(t[r].s);
     84  t[x].a:=0;
     85 end;
     86 
     87 procedure pushup(x:longint);
     88 var l,r:longint;
     89 begin
     90  l:=x<<1; r:=l+1;
     91  t[x].s:=t[l].s+t[r].s; hash(t[x].s);
     92 end;
     93 
     94 procedure build(l,r,p:longint);
     95 var mid:longint;
     96 begin
     97  t[p].l:=r-l+1;
     98  if l=r then exit;
     99  mid:=(l+r)>>1;
    100  build(l,mid,p<<1);
    101  build(mid+1,r,p<<1+1);
    102 end;
    103 
    104 function query(l,r,x,y,p:longint):longint;
    105 var mid:longint;
    106 begin
    107  if (l>=x)and(r<=y) then exit(t[p].s);
    108  mid:=(l+r)>>1;
    109  pushdown(p);
    110  query:=0;
    111  if x<=mid then query:=query+query(l,mid,x,y,p<<1);
    112  if y>mid then query:=query+query(mid+1,r,x,y,p<<1+1);
    113 // if query>=mo then query:=query-mo;
    114  hash(query);
    115 end;
    116 
    117 procedure update(l,r,x,y,p:longint);
    118 var mid:longint;
    119 begin
    120  if (l>=x)and(r<=y) then
    121  begin
    122   inc(t[p].a);
    123  // if t[p].a>=mo then t[p].a:=t[p].a-mo;
    124   hash(t[p].a);
    125   t[p].s:=t[p].s+t[p].l;
    126   hash(t[p].s);
    127  // if t[p].s>=mo then t[p].s:=t[p].s-mo;
    128   exit;
    129  end;
    130  mid:=(l+r)>>1;
    131  pushdown(p);
    132  if x<=mid then update(l,mid,x,y,p<<1);
    133  if y>mid then update(mid+1,r,x,y,p<<1+1);
    134  pushup(p);
    135 end;
    136 
    137 procedure change(k:longint);
    138 begin
    139  while top[k]<>1 do
    140  begin
    141   update(1,n,tid[top[k]],tid[k],1);
    142   k:=fa[top[k]];
    143  end;
    144  update(1,n,1,tid[k],1);
    145 end;
    146 
    147 function clac(k:longint):longint;
    148 begin
    149  clac:=0;
    150  while top[k]<>1 do
    151  begin
    152   clac:=clac+query(1,n,tid[top[k]],tid[k],1);
    153 //  if clac>=mo then clac:=clac-mo;
    154   hash(clac);
    155   k:=fa[top[k]];
    156  end;
    157  clac:=clac+query(1,n,1,tid[k],1);
    158 // if clac>=mo then clac:=clac-mo;
    159  hash(clac);
    160 end;
    161 
    162 begin
    163  assign(input,'bzoj3626.in'); reset(input);
    164  assign(output,'bzoj3626.out'); rewrite(output);
    165  readln(n,q);
    166  for i:=2 to n do
    167  begin
    168   read(fa[i]); inc(fa[i]);
    169   add(fa[i],i);
    170  end;
    171  dfs1(1);
    172  fillchar(flag,sizeof(flag),0);
    173  dfs2(1,1);
    174  tot:=0;
    175  for i:=1 to q do
    176  begin
    177   readln(l,r,z);
    178   inc(l); inc(r); inc(z);
    179   addq(l-1,i,z,-1);
    180   addq(r,i,z,1);
    181  end;
    182  build(1,n,1);
    183  for i:=1 to n do
    184  begin
    185   change(i);
    186   e:=head1[i];
    187   while e<>0 do
    188   begin
    189    v:=vet1[e]; j:=c[e]; f:=d[e];
    190    ans[v]:=(ans[v]+f*clac(j) mod mo+mo) mod mo;
    191    e:=next1[e];
    192   end;
    193  end;
    194  for i:=1 to q do writeln(ans[i]);
    195 
    196  close(input);
    197  close(output);
    198 end.
  • 相关阅读:
    MYSQL 优化(二),持续更新收藏
    一些linux命令 备份下
    lsyncd +xinetd+syncd 多服务器文件同步
    阿里slb+ecs+https
    微擎 从 php5 到php7 的各种填坑 持续更新
    lmap
    微擎的ifp ife ifpp
    工具索引 mark名字
    Funny Bug || Sky Hole
    mysql 查询小技巧
  • 原文地址:https://www.cnblogs.com/myx12345/p/6425813.html
Copyright © 2020-2023  润新知