题目背景

NOIP2016 提高组 Day1 T2

题目描述

小 C 同学认为跑步非常有趣,于是决定制作一款叫做《天天爱跑步》的游戏。《天天爱跑步》是一个养成类游戏,需要玩家每天按时上线,完成打卡任务。

这个游戏的地图可以看作一一棵包含 n 个结点和 n-1 条边的树, 每条边连接两个结点,且任意两个结点存在一条路径互相可达。树上结点编号为从 1 到 n 的连续正整数。

现在有 m 个玩家,第 i 个玩家的起点为 Si ,终点为 Ti 。每天打卡任务开始时,所有玩家在第 0 秒同时从自己的起点出发,以每秒跑一条边的速度,不间断地沿着最短路径向着自己的终点跑去, 跑到终点后该玩家就算完成了打卡任务。 (由于地图是一棵树, 所以每个人的路径是唯一的)

小 C 想知道游戏的活跃度, 所以在每个结点上都放置了一个观察员。 在结点 j 的观察员会选择在第 Wj 秒观察玩家, 一个玩家能被这个观察员观察到当且仅当该玩家在第 Wj 秒也正好到达了结点 j 。 小 C 想知道每个观察员会观察到多少人?

注意: 我们认为一个玩家到达自己的终点后该玩家就会结束游戏, 他不能等待一段时间后再被观察员观察到。 即对于把结点 j 作为终点的玩家: 若他在第  Wj 秒前到达终点,则在结点 j 的观察员不能观察到该玩家;若他正好在第 Wj 秒到达终点,则在结点 j 的观察员可以观察到这个玩家。

输入格式

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

输出格式

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

样例数据 1

输入

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

输出

2 0 0 1 1 1

样例数据 2

输入

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

输出

1 2 1 0 1

备注

【样例1说明】

  • 对于 1 号点,W1 = 0 ,故只有起点为 1 号点的玩家才会被观察到,所以玩家 1 和玩家 2 被观察到,共有 2 人被观察到。
  • 对于 2 号点,没有玩家在第 2 秒时在此结点,共 0 人被观察到。
  • 对于 3 号点,没有玩家在第 5 秒时在此结点,共 0 人被观察到。
  • 对于 4 号点,玩家 1 被观察到,共 1 人被观察到。
  • 对于 5 号点,玩家 1 被观察到,共 1 人被观察到。
  • 对于 6 号点,玩家 3 被观察到,共 1 人被观察到。

【数据规模与约定】

【提示】
如果你的程序需要用到较大的栈空间(这通常意味着需要较深层数的递归),请务必仔细阅读选手目录下的文档“running/stack.pdf”,以了解在最终评测时栈空间的限制与在当前工作环境下调整栈空间限制的方法。

附:running/stack.pdf 文件内容

在最终评测时,调用栈占用的空间大小不会有单独的限制,但在我们的工作环境中默认会有 8 MB  的限制。这可能会引起函数调用层数较多时,程序发生栈溢出崩溃。

我们可以使用一些方法修改调用栈的大小限制。例如,在终端中输入下列命令:

ulimit -s 1048576

此命令的意义是,将调用栈的大小限制修改为 1 GB。

例如,在选手目录建立如下sample.cpp 或 sample.pas

将上述源代码编译为可执行文件 sample 后,可以在终端中运行如下命令运行该程序

./sample

如果在没有使用命令“ulimit -s 1048576”的情况下运行该程序,sample 会因为栈溢出而崩溃;如果使用了上述命令后运行该程序,该程序则不会崩溃。

特别地,当你打开多个终端时,它们并不会共享该命令,你需要分别对它们运行该命令。

请注意,调用栈占用的空间会计入总空间占用中,和程序其他部分占用的内存共同受到内存限制。

解析:

终于把这个万年老坑给填上了。。。

首先考虑起点都在根节点的情况,则一个点的观察员能观察到选手的必要条件是:

对于这种情况,一个点的答案即为以这个点为根的子树内的终点数量。

然后考虑终点都在根节点的情况,则一个点的观察员能观察到到选手的必要条件是:

等价转化后:

对于这种情况,一个点的答案即为以这个点为根的子树内的起点满足的数量。

最后考虑一般情况,步骤分已经再提示我们将路径拆分成两部分。

那么对于一个一般路径,拆成从 u 走到 lca(u,v) 和 lca(u,v) 走到 v 两部分。

对于第一部分,一个点的观察员能观察到的必要条件为:

对于第二部分,一个点的观察员能观察到的必要条件为:

等价转化后:

所以我们对于每个点分别维护两个桶,一个用于存起点,一个用于存终点,由于每个同要维护多个值的数量,所以从子树暴力更新到根是不行的。这里可以利用类似前缀和的思想,先记录下搜索这个点之前的对应信息,搜完这个点及子树后做差求和即可。

所以就是一道树上差分,时间复杂度近似于

代码:

#include <bits/stdc++.h>
using namespace std;const int Add=300000;
const int Max=300005;
int n,m,s,tot;
int first[Max],dep[Max],top[Max],fa[Max],son[Max],size[Max];
int sum1[Max],sum2[Max<<1],w[Max],ans[Max];
vector<int> sum[Max][2],add[Max][2];
struct shu{int to,next;}edge[Max<<1];inline int get_int()
{int x=0,f=1;char c;for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());if(c=='-') f=-1,c=getchar();for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';return x*f;
}
inline void print(int x)
{if(x>9) print(x/10);putchar('0'+x%10);
}inline void build(int x,int y)
{edge[++s].next=first[x],first[x]=s,edge[s].to=y;
}
void dfs1(int p)
{size[p]=1;for(int u=first[p];u;u=edge[u].next){int to=edge[u].to;if(to==fa[p]) continue;fa[to]=p,dep[to]=dep[p]+1,dfs1(to),size[p]+=size[to];if(size[to]>size[son[p]]) son[p]=to;}
}
void dfs2(int p,int tp)
{top[p]=tp;if(!son[p]) return;dfs2(son[p],tp);for(int u=first[p];u;u=edge[u].next){int to=edge[u].to;if(to==fa[p]||to==son[p]) continue;dfs2(to,to);}
}
inline int LCA(int x,int y)
{while(top[x]^top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);x=fa[top[x]];}return dep[x]<dep[y]?x:y;
}
void dfs(int p)
{int x1=w[p]+dep[p],x2=w[p]-dep[p],pre1=sum1[x1],pre2=sum2[x2+Add];for(int u=first[p];u;u=edge[u].next){int to=edge[u].to;if(to==fa[p]) continue;dfs(to);}for(int i=0;i<sum[p][0].size();i++) sum1[sum[p][0][i]]+=add[p][0][i];for(int i=0;i<sum[p][1].size();i++) sum2[sum[p][1][i]+Add]+=add[p][1][i];ans[p]+=sum1[x1]-pre1,ans[p]+=sum2[x2+Add]-pre2;
}int main()
{n=get_int(),m=get_int();for(int i=1;i<n;i++){int x=get_int(),y=get_int();build(x,y),build(y,x);}for(int i=1;i<=n;i++) w[i]=get_int();dfs1(1),dfs2(1,1);while(m--){int x=get_int(),y=get_int(),f=LCA(x,y);sum[x][0].push_back(dep[x]),add[x][0].push_back(1);sum[y][1].push_back(dep[x]-2*dep[f]),add[y][1].push_back(1);sum[f][0].push_back(dep[x]),add[f][0].push_back(-1);sum[fa[f]][1].push_back(dep[x]-2*dep[f]),add[fa[f]][1].push_back(-1);}dfs(1);for(int i=1;i<=n;i++) print(ans[i]),putchar(' ');return 0;
}

【NOIP2016提高组】天天爱跑步相关推荐

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

    如果没有时间的限制,这题就是对每个点iii,求经过iii的路径数,用树上差分解决即可: 枚举路径x→y{x\to y\{x→y{ a[x]+=1;a[y]+=1;a[x]+=1;a[y]+=1;a[x ...

  2. NOIP2016提高组 天天爱跑步

    (树上差分 + \(LCA\)) \(O(Mlog_2N)\) 调了两个小时,最后发现把\(lca\)里的\(y\)写成\(x\)了,当场去世. 首先下几个定义: \(dis[x]\) 为\(x\)到 ...

  3. P1850 [NOIP2016 提高组] 换教室

    P1850 [NOIP2016 提高组] 换教室 题意: 有2n个课安排在n个时间段上,每个时间段上都有两个一样的课同时在不同地方上,起初牛牛被所有课都被安排在Ci上课,另一节课在Di上课.牛牛现在想 ...

  4. [NOIP2016 提高组] 愤怒的小鸟

    [NOIP2016 提高组] 愤怒的小鸟 题意: 有n只猪,给出猪的坐标(xi,yi),问最少用几个形如 y=ax^2+bx 的曲线可以保证所有猪在曲线上,满足a<0,a,b为实数 n<= ...

  5. #185. [NOIP2016 提高组] 蚯蚓题解

    #185. [NOIP2016 提高组] 蚯蚓题解 题目描述 本题中,我们将用符号 ⌊c⌋\lfloor c \rfloor⌊c⌋ 表示对 ccc 向下取整,例如:⌊3.0⌋=⌊3.1⌋=⌊3.9⌋= ...

  6. NOIP2016提高组 第一天第二题 天天爱跑步running 题解

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

  7. NOIP2016 提高组 解题报告

    说明:由于我能力的限制,文章中的做法不一定是最优秀的算法,但官方数据全部测试通过,使用的全部知识全部是NOIP提高组的知识,请组织放心查看. 感谢 GoodQt 的指导与帮助 DAY1 T1 玩具谜题 ...

  8. NOIP2016提高组复赛解题报告

    Day1 T1-玩具谜题 Day1 T2-天天爱跑步 Day1 T3-换教室 Day2 T1-组合数问题 Day2 T2-蚯蚓 Day2 T3-愤怒的小鸟 转载于:https://www.cnblog ...

  9. noip2016 day1 t2 天天爱跑步

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

最新文章

  1. querywrapper or and嵌套_两个经常用的逻辑函数AND函数,OR函数
  2. 190401装饰器-高阶函数-闭包
  3. 第五天2017/04/06(上午:文件的“读写操作”)
  4. 史上最可爱的关系抽取指南?从一条规则到十个开源项目
  5. 多线程编程(14) - 多线程同步之 WaitableTimer (等待定时器对象)
  6. 一文读懂Http Headers为何物(超详细)
  7. mysql语句6_MySQL的SQL语句 - 数据操作语句(6)- INSERT 语句
  8. 灰狼/狼群算法优化支持向量机SVM分类预测matlab代码,支持多分类。 Excel数据格式 ,直接运行 。
  9. hermite插值matlab代码,hermite插值以及两种MATLAB程序
  10. 一个人竟然撸了一个百度网盘客户端
  11. 任正非对姚安娜是劝退式支持吗
  12. 新浪股权分散是把双刃剑
  13. 图像Randon变换含Matlab源码
  14. 中国移动dns服务器没有响应,江苏移动宽带DNS设置方法及常见问题
  15. 渲染到纹理(Render To Texture, RTT)
  16. ft232h引脚_K9K8G08U0B-PIB0--斗门--镁光MICRON内存收购
  17. cache line大小
  18. 《滴滴重MVVM框架Chameleon》架构篇读后感
  19. 网站压力测试工具was
  20. zookeeper为什么是CP原则

热门文章

  1. [ZUCC 计网]BB-quiz-数据链路层测试-2020
  2. mpstat命令(linux cpu监控工具)
  3. lsdyna材料定义(1) lsprepost
  4. spring boot新闻管理系统 毕业设计源码211113
  5. windows10 自带的office突然无缘故被卸载了
  6. 淘宝、天猫API接口
  7. 产品经理撰写需求文档
  8. 解决No such file or directory: /turtlebot3/turtlebot3_description/urdf/turtlebot3_.urdf.xacro
  9. Cadence学习七:给板子外形倒角
  10. M1 Mac安装 PS 2021 闪退、卡启动界面解决方法