[NOIP2016-day1-T2]天天爱跑步running_题解

题目来源:http://www.lydsy.com/JudgeOnline/problem.php?id=4719

镇楼图:

noip滚粗后、、订正的第一题。

题目大意:

有若干条路径在一棵树上,问每个点恰为多少条路径起点出发Ti长度处。

解题方略:

这题可以O(n)。。结果shy非常有趣地在考场上码80分暴力、结果还爆QAQ(这题,80分做法,比100分做法难吧。。)

考虑把询问分成不同的两个链。但是,如果有链的话,就不可避免要树剖(就是因为他不像联赛算法,shy考试时才没写QWQ)。然而其实不必。利用DFS的性质,可以知道,在一个点打标记,可以影响到它的子树(相对地,也可以是所有父亲)。那么,我们考虑暴力,就是询问每个点x,子树里有多少个d[u]=d[x]+t[x]或d[v]-len[u,v]=d[x]-t[x],复杂度O(n*子树大小)。那么,这个只要一个桶就可以记录。求LCA只要tarjan离线就可以O(n+m),这里暂时把并查集的复杂度也看成常数倍。那么,有些人就会卡在子树的合并上。其实并不用合并。因为,一个点退出时,我们即知,其子树的操作都已经实施过(添加/删除),那么,我们只需在进入时算一遍Ans、退出时算一遍Ans,两者的差就是子树的贡献。

AC代码:

这里bzoj之前数据有漏导致WA了,事情咋那么多呢TAT。

 1 {$M 100000000,0,100000000}
 2 type
 3  Chitose=record
 4   e:longint;
 5   head     :array[0..300005]of longint;
 6   next,node:array[0..600005]of longint
 7  end;
 8  Chitoge=array[-600005..600005]of longint;
 9 var
10  n,m,i,u,v:longint;
11  t,d,z,s,Ans:array[0..300005]of longint;
12  p,q:Chitoge;
13  o,a:Chitose;
14  f,g:array[0..1]of Chitose;
15
16 procedure ad(var x:Chitose;u,v:longint);
17 begin
18  with x do
19  begin
20   inc(e);
21   next[e]:=head[u];
22   head[u]:=e;
23   node[e]:=v
24  end
25 end;
26
27 function fd(x:longint):longint;
28 begin if x<>z[x] then z[x]:=fd(z[x]); exit(z[x]) end;
29
30 procedure sk(u:longint);
31 var i,v,w,x,y,c:longint;
32 begin
33  z[u]:=u;
34  i:=o.head[u];
35  while i<>0 do
36  begin
37   v:=o.node[i];
38   if d[v]=0 then begin d[v]:=d[u]+1; sk(v); z[v]:=u end;
39   i:=o.next[i]
40  end;
41  i:=a.head[u];
42  while i<>0 do
43  begin
44   w:=a.node[i]>>1;
45   if s[w]=0 then s[w]:=u
46       else begin v:=s[w];
47                  c:=fd(v);
48                  s[w]:=d[v]+d[u]-2*d[c];
49                  if odd(a.node[i]) then begin x:=v; y:=u end
50                                    else begin x:=u; y:=v end;
51                  ad(f[0],x,d[x]);
52                  ad(f[1],c,d[x]);
53                  ad(g[0],y,d[y]-s[w]);
54                  ad(g[1],c,d[y]-s[w]) end;
55   i:=a.next[i]
56  end
57 end;
58
59 procedure __Claris(u:longint);
60 var i,v:longint;
61 begin
62  z[u]:=0;
63  Ans[u]:=p[d[u]+t[u]]+q[d[u]-t[u]];
64  i:=f[0].head[u]; while i<>0 do begin inc(p[f[0].node[i]]); i:=f[0].next[i] end;
65  i:=g[0].head[u]; while i<>0 do begin inc(q[g[0].node[i]]); i:=g[0].next[i] end;
66  i:=o.head[u];
67  while i<>0 do
68  begin
69   v:=o.node[i];
70   if z[v]<>0 then __Claris(v);
71   i:=o.next[i]
72  end;
73  i:=f[1].head[u]; while i<>0 do begin dec(p[f[1].node[i]]); i:=f[1].next[i] end; Ans[u]:=p[d[u]+t[u]]+q[d[u]-t[u]]-Ans[u];
74  i:=g[1].head[u]; while i<>0 do begin dec(q[g[1].node[i]]); i:=g[1].next[i] end;
75 end;
76
77 begin
78  read(n,m);
79  for i:=2 to n do
80  begin
81   read(u,v);
82   ad(o,u,v);
83   ad(o,v,u)
84  end;
85  for i:=1 to n do read(t[i]);
86  for i:=1 to m do
87  begin
88   read(u,v);
89   ad(a,u,i<<1);
90   ad(a,v,i<<1+1)
91  end;
92  d[1]:=1;
93  sk(1);
94  __Claris(1);
95  write(Ans[1]); for i:=2 to n do write(‘ ‘,Ans[i])
96 end.
时间: 2024-10-21 21:07:13

[NOIP2016-day1-T2]天天爱跑步running_题解的相关文章

NOIP 2016 Day1 T2 天天爱跑步

题目大意 给定一个n个节点,n?1条边的树.有m个玩家,第i个玩家从xi走树上最短路径到yi.玩家第0秒在自己的起点上,然后每秒移动一条边,移动到终点后结束移动. 每个节点上有一个观察员以及权值wi.如果有一个玩家在其移动的第wi秒恰好到达这个点,那么这个点上的观察员就会观察到他(如果这个点是终点,且玩家在wi秒之前到达不算). 求每个点上的观察员分别观察到了多少个玩家. 1≤n≤299998,1≤m≤299998 题目分析 我们将每条路径拆成从出发点到lca,和从lca的下一个点到结束点两段.

[NOIp2016提高组]天天爱跑步

题目大意: 有一棵n个点的树,每个点上有一个摄像头会在第w[i]秒拍照. 有m个人再树上跑,第i个人沿着s[i]到t[i]的路径跑,每秒钟跑一条边. 跑到t[i]的下一秒,人就会消失. 问每个摄像头会拍下几个人. 思路: 首先很显然是要求LCA的. 求完LCA怎么办? 我们可以用树上差分的方法分别维护向上.向下的链. 每一条路径,我们可以在s,t,lca,par[lca]上分别打标记. s +dep[s] t +dep[t]-len lca -dep[s] par[lca] +len-dep[t

[luogu]P1600 天天爱跑步[LCA]

[luogu]P1600 [NOIP 2016]天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含n个结点和n−1条边的树, 每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到n的连续正整数. 现在有m个玩家,第i个玩家的起点为Si?,终点为Ti? .每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速

天天爱跑步[NOIP2016]

时间限制:2 s   内存限制:512 MB [题目描述] 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一棵包含n个结点和n-1条边的树,每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到n的连续正整数. 现在有m个玩家,第i个玩家的起点为Si,终点为Ti.每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发,以每秒跑一条边的速度,不间断

NOIP2016天天爱跑步

2557. [NOIP2016]天天爱跑步 时间限制:2 s   内存限制:512 MB [题目描述] 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一棵包含n个结点和n-1条边的树,每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到n的连续正整数. 现在有m个玩家,第i个玩家的起点为Si,终点为Ti.每天打卡任务开始时,所有玩家在第0秒同时从

【NOIP2016】天天爱跑步

Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一棵包含n个结点和n-1条边的树,每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到n的连续正整数. 现在有m个玩家,第i个玩家的起点为Si,终点为Ti.每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发,以每秒跑一条边的速度,不间断地沿着最短路径向着自己的终点跑去,跑

bzoj4719[Noip2016]天天爱跑步

Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一棵包含 N个结点和N-1 条边的树, 每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到N的连续正整数.现在有个玩家,第个玩家的起点为Si ,终点为Ti  .每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速度,不间断地沿着最短路径向着自己的终点跑去, 跑到

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

题意: 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一棵包含 N个结点和N-1 条边的树, 每条边连接两 个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到N的连续正整数.现在有个玩家,第个玩家的 起点为Si ,终点为Ti  .每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速度, 不间断地沿着最短路径向着自己的终点跑去, 跑到终点后该

bzoj 4719: [Noip2016]天天爱跑步

Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一棵包含 N个结点和N-1 条边的树, 每条边连接两 个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到N的连续正整数.现在有个玩家,第个玩家的 起点为Si ,终点为Ti  .每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速度, 不间断地沿着最短路径向着自己的终点跑去