Description

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

Input

第一行有两个整数N和M 。其中N代表树的结点数量, 同时也是观察员的数量, M代表玩家的数量。
接下来n-1 行每行两个整数U和V ,表示结点U 到结点V 有一条边。
接下来一行N 个整数,其中第个整数为Wj , 表示结点出现观察员的时间。
接下来 M行,每行两个整数Si和Ti,表示一个玩家的起点和终点。
对于所有的数据,保证 。
1<=Si,Ti<=N,0<=Wj<=N

Output

输出1行N 个整数,第个整数表示结点的观察员可以观察到多少人。

Sample Input

6 3
2 3
1 2
1 4
4 5
4 6
0 2 5 1 2 3
1 5
1 3
2 6

Sample Output

2 0 0 1 1 1
 

lydrainbowcat讲的真是炒鸡棒啊,这里主要参考他在sfjsjjzn上的讲解

首先,每个玩家跑步的路线可以分成两部分:$S$->$lca(S,T)$  $lca(S,T)$->$T$,后者不包括lca

那么,如果位于节点x的观察员能看到玩家i,当且仅当满足:

1.x在S到lca的路径上,且满足$dep[S_i]-dep[x]=w[x]$

2.x在lca到T的路径上(不含lca),且满足$dep[S_i]+dep[x]-2*dep[lca]=w[x]$

接下来分开计算这两种观察员,最后相加即可

首先看一道题

我们的这道题也可以转化成“路径上投放物品”的问题

以第一种观察员的情况为例

由$dep[S_i]-dep[x]=w[x]$

可得$dep[S_i]=dep[x]+w[x]$

就可以理解为给S到lca的路径上的每个点添加类型为$dep[S_i]$的物品

所求为每个点$w[x]+dep[x]$类型的物品有多少

使用树上差分,将其转化为:

点S处生成物品$dep[S_i]$,点lca处这种物品消失

同理,第二种观察员可以转化为$dep[S_i]-2*dep[lca]$在T生成,在lca消失

所求为$w[x]-dep[x]$的物品数量

权值线段树合并确实是可以的,但本题不需要维护最值,只是求特定数量

所以可以对每个点开vector,把物品的生成和消失记录存在里面

最后统计的时候  开一个数组cnt[]用于统计数量(不是每个点开一个!运用差分的思想!)

递归时先存一下旧的$c[所求]$,回溯的时候用新的值减去它

即为子树和

最后每个点的答案即为两种情况相加

自认为代码可读性还是很高的:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N=;
int n,m,to[N<<],nxt[N<<],head[N],fa[N][],tot=;
int w[N],dep[N],cnt1[N<<],cnt2[N<<],ans1[N],ans2[N];
vector<int> sp[][N],del[][N];
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>'')
{if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')
{x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
}
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void dfs(int x,int deep)
{
dep[x]=deep;
for(int i=;i<=;i++)
fa[x][i]=fa[fa[x][i-]][i-];
for(int i=head[x];i;i=nxt[i])
{
if(dep[to[i]])continue;
fa[to[i]][]=x;
dfs(to[i],deep+);
}
}
int LCA(int x,int y)
{
if(dep[x]>dep[y])swap(x,y);
for(int i=;i>=;i--)
if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
if(x==y)return x;
for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][];
}
void spawn(int pos,int val,int k)
{
sp[k][pos].push_back(val);
}
void remove(int pos,int val,int k)
{
del[k][pos].push_back(val);
}
void cacl1(int x)
{
int now=cnt1[w[x]+dep[x]+n];
for(int i=;i<(int)sp[][x].size();i++)
cnt1[sp[][x][i]]++;
for(int i=;i<(int)del[][x].size();i++)
cnt1[del[][x][i]]--;
for(int i=head[x];i;i=nxt[i])
if(dep[to[i]]>dep[x])cacl1(to[i]);
ans1[x]=cnt1[w[x]+dep[x]+n]-now;
}
void cacl2(int x)
{
int now=cnt2[w[x]-dep[x]+n];
for(int i=;i<(int)sp[][x].size();i++)
cnt2[sp[][x][i]]++;
for(int i=;i<(int)del[][x].size();i++)
cnt2[del[][x][i]]--;
for(int i=head[x];i;i=nxt[i])
if(dep[to[i]]>dep[x])cacl2(to[i]);
ans2[x]=cnt2[w[x]-dep[x]+n]-now;
}
int main()
{
n=read();m=read();
for(int i=;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
for(int i=;i<=n;i++)
w[i]=read();
dfs(,);
for(int i=;i<=m;i++)
{
int S=read(),T=read(),lca=LCA(S,T);
spawn(S,dep[S]+n,);
remove(fa[lca][],dep[S]+n,);
spawn(T,dep[S]-*dep[lca]+n,);
remove(lca,dep[S]-*dep[lca]+n,);
}
cacl1();
cacl2();
for(int i=;i<=n;i++)
printf("%d ",ans1[i]+ans2[i]);
return ;
}

在自家oj上用时是最慢ac的一半,可以说是性价比极高了?

[NOIP2016]天天爱跑步 题解(树上差分) (码长短跑的快)的更多相关文章

  1. [luogu1600 noip2016] 天天爱跑步 (树上差分)

    题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵 ...

  2. ☆ [NOIp2016] 天天爱跑步 「树上差分」

    题目类型:LCA+思维 传送门:>Here< 题意:给出一棵树,有\(M\)个人在这棵树上跑步.每个人都从自己的起点\(s[i]\)跑到终点\(t[i]\),跑过一条边的时间为1秒.现在每 ...

  3. bzoj 4719: [Noip2016]天天爱跑步【树上差分+dfs】

    长久以来的心理阴影?但是其实非常简单-- 预处理出deep和每组st的lca,在这里我简单粗暴的拿树剖爆算了 然后考虑对于一组s t lca来说,被这组贡献的观察员x当且仅当: x在s到lca的路径上 ...

  4. NOIP2016 天天爱跑步(树上差分)

    题意 给定一棵树,从时刻 0 开始,有若干人从 S[i] 出发向 T[i] 移动,每单位时刻移动一条边 对于树上每个点 x,求 w[x]  时刻有多少人恰好路过 x N,M≤300000 题解 从上午 ...

  5. NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】

    题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn个 ...

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

    题意: 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一棵包含 N个结点 ...

  7. [NOIP2016]天天爱跑步-题解

    题面传送门 解答 设第\(j\)号玩家在\(V_j\)时刻出发. 弱化问题:如果树退化成了一条链.则在\(j\)处的观察员能观察到的\(i\)号玩家当且仅当 \[ i玩家经过j,且 \begin{ca ...

  8. LOJ2359. 「NOIP2016」天天爱跑步【树上差分】

    LINK 思路 首先发现如果对于一个节点,假设一个节点需要统计从字数内来的贡献 需要满足\(dep_u - dep_s = w_u\) 这个条件其实可以转化成\(dep_u - w_u = dep_s ...

  9. P1600 [NOIP2016 提高组] 天天爱跑步 (树上差分)

    对于一条路径,s-t,位于该路径上的观察员能观察到运动员当且仅当以下两种情况成立:(d[ ]表示节点深度) 1.观察员x在s-lca(s,t)上时,满足d[s]=d[x]+w[x]就能观察到,所以我们 ...

随机推荐

  1. webpack 兼容低版本浏览器,转换ES6 ES7语法

    ES6,ES7真的太棒了,async +await+Promise,让我阅读代码的时候不用再从左拉到右了(异步太多,一层套一层真的太头痛) 但是有个问题,打包后低版本浏览器运行不了,还有我用了一些混淆 ...

  2. Echarts 甘特图教程

    Echarts甘特图教程  echarts官网实例: https://gallery.echartsjs.com/editor.html?c=xEYpsVs30s 效果:  代码: <html& ...

  3. 数组转xls格式的excel文件&数据转csv格式的excle

    /** * 数组转xls格式的excel文件 * @param array $data 需要生成excel文件的数组 * @param string $filename 生成的excel文件名 * 示 ...

  4. $router和router区别

    this.$router.push({path:'/'})//这个是js编程式的一种动态跳转路由方式,是全局的路由对象. 而写在router声明文件中的router是自己定义实例化的一个对象.可以使用 ...

  5. Python面向对象 杂篇(后记)

    异常处理 什么是异常:         我们在调试程序时,常常会因为各种报错信息导致程序无法运行,异常也是一个对象,用来表示错误.我们可以捕捉异常,并做相应处理,从而增加代码的友好程度. 异常处理: ...

  6. ZROI week4

    考试 前言 起晚了,大概10点才开始看T1,被别人问了T2有点懵逼. 和 这题看了就A掉了,感觉很像原题的样子,是我的错觉吗?? 串串 某神仙有个\(O(n)\)做法问了我一下,我当时也没怎么想(因为 ...

  7. 提供 web前端、H5、html页面 技术服务

    如有前端页面的需求请在评论区留言  第一时间进行回复

  8. linux(centos6) 常用操作

    目录 一.开机关机 1.Linux centos重启命令: 2.Linux centos关机命令: 二.图形界面与命令界面的切换 1.修改/etc/inittab文件,文件中,最后一行id:5:ini ...

  9. Java第四次作业,面向对象高级特性(继承和多态)

    Java第四次作业-面向对象高级特性(继承和多态) (一)学习总结 1.学习使用思维导图对Java面向对象编程的知识点(封装.继承和多态)进行总结. 2.阅读下面程序,分析是否能编译通过?如果不能,说 ...

  10. Linux命令 who

    who :显示当前登入系统的用户信息 显示的内容主要包括: 用户名,登录终端,上线时间,停留时间,动作,UID等 权限:所有使用者 语法: who  [option] ...[ file | arg1 ...