• 【NOIP2016】天天爱跑步(树上差分)


    题意:

    小c同学认为跑步非常有趣,于是决定制作一款叫做《天天爱跑步》的游戏。?天天爱跑步?是一个养成类游戏,需要
    玩家每天按时上线,完成打卡任务。这个游戏的地图可以看作一一棵包含 N个结点和N-1 条边的树, 每条边连接两
    个结点,且任意两个结点存在一条路径互相可达。树上结点编号为从1到N的连续正整数。现在有个玩家,第个玩家的
    起点为Si ,终点为Ti  。每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速度,
    不间断地沿着最短路径向着自己的终点跑去, 跑到终点后该玩家就算完成了打卡任务。 (由于地图是一棵树, 所以
    每个人的路径是唯一的)小C想知道游戏的活跃度, 所以在每个结点上都放置了一个观察员。 在结点的观察员会选
    择在第Wj秒观察玩家, 一个玩家能被这个观察员观察到当且仅当该玩家在第Wj秒也理到达了结点J  。 小C想知道
    每个观察员会观察到多少人?注意: 我们认为一个玩家到达自己的终点后该玩家就会结束游戏, 他不能等待一 段时
    间后再被观察员观察到。 即对于把结点J作为终点的玩家: 若他在第Wj秒重到达终点,则在结点J的观察员不能观察
    到该玩家;若他正好在第Wj秒到达终点,则在结点的观察员可以观察到这个玩家。

    思路:From http://blog.csdn.net/doyouseeman/article/details/53385565

    我们思考一下从x到y的路径,
    这个可以拆成从x到lca的路径和从lca到y的路径,这个很明显。
    如果一个点i在从x到lca 的路径可以检测到的话,
    那么就有deep[i]+w[i]=deep[x]。
    如果一个点i在从lca到y的路径上可以检测到的话,
    那么就有deep[i]-w[i]=deep[y]-t(t表示x到y的路径长度)。
    那么用树链剖分的方法很容易,但是很慢。有一个用桶的方法,跑得很快。
    维护两个桶,一个向上的桶a和一个向下的桶b。
    从x到y的一个路径,在x中a[deep[x]]加一个,当dfs把lca退栈的时候,x的影响就没有了,那么把a[deep[x]]减掉。
    在lca那里需要把一个b[deep[y]]加进来,在y出栈后,就把b[deep[y]]减掉。
    每次ans[x]的答案就是子树a[deep[x]+w[x]]+b[deep[x]-w[x]]的数量。
    但是如果是一条链的情况,那么这样会算重,所以还要减去重复的数量。

      1 var shang,xia:array[-310000..310000]of longint;
      2     head,head1,head2,head3:array[1..6100000]of longint;
      3     vet,vet1,vet2,vet3,
      4     next,next1,next2,next3,ans,dep,a,s:array[1..610000]of longint;
      5     f:array[1..310000,0..20]of longint;
      6     n,m,i,x,y,q,b,tot,tot1,tot2,tot3,t:longint;
      7 
      8 procedure add(a,b:longint);
      9 begin
     10  inc(tot);
     11  next[tot]:=head[a];
     12  vet[tot]:=b;
     13  head[a]:=tot;
     14 end;
     15 
     16 procedure add1(a,b:longint);
     17 begin
     18  inc(tot1);
     19  next1[tot1]:=head1[a];
     20  vet1[tot1]:=b;
     21  head1[a]:=tot1;
     22 end;
     23 
     24 procedure add2(a,b:longint);
     25 begin
     26  inc(tot2);
     27  next2[tot2]:=head2[a];
     28  vet2[tot2]:=b;
     29  head2[a]:=tot2;
     30 end;
     31 
     32 procedure add3(a,b:longint);
     33 begin
     34  inc(tot3);
     35  next3[tot3]:=head3[a];
     36  vet3[tot3]:=b;
     37  head3[a]:=tot3;
     38 end;
     39 
     40 procedure dfs(u,fa:longint);
     41 var e,v,i:longint;
     42 begin
     43  for i:=1 to 20 do
     44  begin
     45   if dep[u]<(1<<i) then break;
     46   f[u,i]:=f[f[u,i-1],i-1];
     47  end;
     48  e:=head[u];
     49  while e<>0 do
     50  begin
     51   v:=vet[e];
     52   if v<>fa then
     53   begin
     54    f[v,0]:=u;
     55    dep[v]:=dep[u]+1;
     56    dfs(v,u);
     57   end;
     58   e:=next[e];
     59  end;
     60 end;
     61 
     62 procedure swap(var x,y:longint);
     63 var t:longint;
     64 begin
     65  t:=x; x:=y; y:=t;
     66 end;
     67 
     68 function lca(x,y:longint):longint;
     69 var i,d:longint;
     70 begin
     71  if dep[x]<dep[y] then swap(x,y);
     72  d:=dep[x]-dep[y];
     73  for i:=0 to 20 do
     74   if d and (1<<i)>0 then x:=f[x,i];
     75  for i:=20 downto 0 do
     76   if f[x,i]<>f[y,i] then
     77   begin
     78    x:=f[x,i]; y:=f[y,i];
     79   end;
     80  if x=y then exit(x);
     81  exit(f[x,0]);
     82 end;
     83 
     84 procedure dfs1(u,fa:longint);
     85 var e,v,x,y:longint;
     86 begin
     87  x:=xia[dep[u]+a[u]];
     88  y:=shang[dep[u]-a[u]];
     89  xia[dep[u]]:=xia[dep[u]]+s[u];
     90  e:=head1[u];
     91  while e<>0 do
     92  begin
     93   v:=vet1[e];
     94   inc(shang[v]);
     95   e:=next1[e];
     96  end;
     97  e:=head[u];
     98  while e<>0 do
     99  begin
    100   v:=vet[e];
    101   if v<>fa then dfs1(v,u);
    102   e:=next[e];
    103  end;
    104  ans[u]:=xia[dep[u]+a[u]]+shang[dep[u]-a[u]]-x-y;
    105  e:=head2[u];
    106  while e<>0 do
    107  begin
    108   v:=vet2[e];
    109   dec(xia[v]);
    110   if v=dep[u]+a[u] then dec(ans[u]);
    111   e:=next2[e];
    112  end;
    113  e:=head3[u];
    114  while e<>0 do
    115  begin
    116   v:=vet3[e];
    117   dec(shang[v]);
    118   e:=next3[e];
    119  end;
    120 end;
    121 
    122 begin
    123  assign(input,'bzoj4719.in'); reset(input);
    124  assign(output,'bzoj4719.out'); rewrite(output);
    125  readln(n,m);
    126  for i:=1 to n-1 do
    127  begin
    128   readln(x,y);
    129   add(x,y); add(y,x);
    130  end;
    131  dfs(1,0);
    132  for i:=1 to n do read(a[i]);
    133  for i:=1 to m do
    134  begin
    135   readln(x,y);
    136   q:=lca(x,y);
    137   t:=dep[x]+dep[y]-2*dep[q];
    138   inc(s[x]); b:=dep[y]-t;
    139   add1(y,b);
    140   add2(q,dep[x]);
    141   add3(q,b);
    142  end;
    143  dfs1(1,0);
    144  for i:=1 to n-1 do write(ans[i],' ');
    145  write(ans[n]);
    146  close(input);
    147  close(output);
    148 end.
  • 相关阅读:
    Flask第二篇——服务器相关
    Flask第一篇——URL详解
    Appium 定位方法例子(4)
    selenium 上传文件方法补充——SendKeys、win32gui
    Appium+python (3) 异常处理
    Appium+python (3) 元素定位(1)
    "http://127.0.0.1:4723/wd/hub"的解释
    Appium + Python App自动化(2)第一个脚本
    Appium+python(1)简单的介绍环境搭建
    用fiddler设置手机代理
  • 原文地址:https://www.cnblogs.com/myx12345/p/7425300.html
Copyright © 2020-2023  润新知