[noip2016]天天爱跑步

2024-08-23 16:08
文章标签 跑步 天天 noip2016

本文主要是介绍[noip2016]天天爱跑步,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

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

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

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

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

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

输入输出格式

输入格式:

第一行有两个整数n和m 。其中n代表树的结点数量, 同时也是观察员的数量, m代表玩家的数量。

接下来 n- 1行每行两个整数u和 v,表示结点 u到结点 v有一条边。

接下来一行 n个整数,其中第j个整数为W_j , 表示结点j出现观察员的时间。

接下来 m行,每行两个整数S_i,和T_i,表示一个玩家的起点和终点。

对于所有的数据,保证1\leq S_i,T_i\leq n, 0\leq W_j\leq n 。

输出格式:

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


个人思路:

  • 类似"雨天的尾巴",在dfs的过程中合并数据即可。可以注意到W范围较大,且区间具有可合并性(非最大/小值等操作).
  • 因此,可利用vector维护每个点上"玩家"的增加/减少情况,再在dfs的过程中利用全局数组合并即可.
  • 具体地说,对于每个玩家,分成两段分别考虑,即S->LCA和LCA->T。可以发现,在第一种情况下满足W[x]-d[x]=d[s];在第二种情况下满足W[x]-d[x]=d[s]-2*d[lca(s,t)].
  • 代入树上差分的基本过程中可以发现:在第一种情况下,利用区间合并使得lca(s,t)与s之间的点可以利用该情况的数据,第二种情况同理。当然,也可以直接用两个局部变量cnt1,cnt2分别维护W[x]-d[x],W[x]+d[x],并在一次dfs中求得结果.

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1000010,MAXM=1000010;
struct Edge{int from,to,nxt;
}e[MAXM];
int head[MAXN],edgeCnt=1;
void addEdge(int u,int v){e[++edgeCnt].from=u;e[edgeCnt].to=v;e[edgeCnt].nxt=head[u];head[u]=edgeCnt;
}
int dep[MAXN],f[MAXN][21];
void dfs_Lca(int x){dep[x]=dep[f[x][0]]+1;for(int i=1;i<=20;i++){f[x][i]=f[f[x][i-1]][i-1];}for(int i=head[x];i;i=e[i].nxt){int v=e[i].to;if(!dep[v]){f[v][0]=x;dfs_Lca(v);}}
}
int lca(int a,int b){if(dep[a]>dep[b])swap(a,b);for(int i=20;i>=0;i--){if(dep[b]-(1<<i)>=dep[a])b=f[b][i];}if(a==b)return a;for(int i=20;i>=0;i--)if(f[a][i]!=f[b][i])a=f[a][i],b=f[b][i];return f[a][0];
}int w[MAXN];
struct player{int s,t;
}players[MAXN];
struct item{int pos,value;
};
vector<item> vecs_First[MAXN];
int c[MAXN],ans[MAXN];
void dfs_Solve_First(int x){int cnt=c[w[x]+dep[x]];for(int i=head[x];i;i=e[i].nxt){int v=e[i].to;if(v!=f[x][0]){dfs_Solve_First(v);}}while(!vecs_First[x].empty()){item nowItem=vecs_First[x].back();vecs_First[x].pop_back();int nowPos=nowItem.pos,nowValue=nowItem.value;c[nowPos]+=nowValue;}ans[x]+=c[w[x]+dep[x]]-cnt;
}
void init(){memset(c,0,sizeof(c));}
vector<item> vecs_Second[MAXN];
void dfs_Solve_Second(int x){int cnt=c[w[x]-dep[x]];for(int i=head[x];i;i=e[i].nxt){int v=e[i].to;if(v!=f[x][0]){dfs_Solve_Second(v);}}while(!vecs_Second[x].empty()){item nowItem=vecs_Second[x].back();vecs_Second[x].pop_back();int nowPos=nowItem.pos,nowValue=nowItem.value;c[nowPos]+=nowValue;}ans[x]+=c[w[x]-dep[x]]-cnt;
}
int main(){int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n-1;i++){int u,v;scanf("%d%d",&u,&v);addEdge(u,v);addEdge(v,u);}f[1][0]=0;dfs_Lca(1);for(int i=1;i<=n;i++){scanf("%d",&w[i]);}for(int i=1;i<=m;i++){scanf("%d%d",&players[i].s,&players[i].t);vecs_First[players[i].s].push_back(item{dep[players[i].s],1});vecs_First[f[lca(players[i].s,players[i].t)][0]].push_back(item{dep[players[i].s],-1});vecs_Second[players[i].t].push_back(item{dep[players[i].s]-2*dep[lca(players[i].s,players[i].t)],1});vecs_Second[lca(players[i].s,players[i].t)].push_back(item{dep[players[i].s]-2*dep[lca(players[i].s,players[i].t)],-1});}dfs_Solve_First(1);init();dfs_Solve_Second(1);for(int i=1;i<=n-1;i++){cout<<ans[i]<<" ";}printf("%d\n",ans[n]);return 0;
}

 

这篇关于[noip2016]天天爱跑步的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1099856

相关文章

天天爱你的心永不变

爱一个人,能够爱多久,很多人都有这个疑问,很多人对于天长地久的爱情都存在怀疑。其实,就是你的怀疑让你的爱情在慢慢失去原来的味道,是你的怀疑将你的爱情逐渐推离你的生活。

信息学奥赛初赛天天练-83-NOIP2014普及组-基础题2-输入设备、输出设备、操作系统、二进制、整数除法、while、do while循环

1 NOIP 2014 普及组 基础题2 4 以下哪一种设备属于输出设备( ) A 扫描仪 B 键盘 C 鼠标 D 打印机 5 下列对操作系统功能的描述最为完整的是( ) A 负责外设与主机之间的信息交换 B 负责诊断机器的故障 C 控制和管理计算机系统的各种硬件和软件资源的使用 D 将没有程序编译成目标程序 11 下列各无符号十进制整数中,能用八位二进制表示的数中最大的是( ) A 296

跑步用耳机哪款好?这五款运动骨传导耳机健身人士都说好!

在无线耳机市场持续繁荣的今天,入耳式耳机以其卓越的音质体验赢得了众多用户的青睐。然而,随着健康意识的提升,长时间佩戴入耳式耳机所带来的健康隐患日益受到关注。正是在这样的背景下,骨传导耳机凭借其独特的非入耳式设计,开启了健康聆听的新篇章。它不仅有效保护了耳道健康,减少了佩戴不适,还确保了用户在享受音乐的同时,能够随时感知外界环境,为日常出行增添一份安全保障。 面对纷繁复杂的骨传导耳机市场,如何挑选

信息学奥赛初赛天天练-80-NOIP2015普及组-基础题5-错位排列、二叉树、完全二叉树、叶子节点、完全二叉树叶子节点

NOIP 2015 普及组 基础题5 21 重新排列 1234使得每一个数字都不在原来的位置上,一共有( )种排法 22 一棵结点数为 2015的二叉树最多有( )个叶子结点 2 相关知识点 1) 错位排列 考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。 n个元素的错排数记为D(n) 错排问题最早被尼古拉·伯努利和欧拉研究

信息学奥赛初赛天天练-79-NOIP2015普及组-基础题4-即时通讯软件、二叉树遍历、前序遍历、中序遍历、后序遍历、算法时间复杂度

NOIP 2015 普及组 基础题4 11 下面哪种软件不属于即时通信软件( ) A QQ B MSN C 微信 D P2P 16 前序遍历序列与中序遍历序列相同的二叉树为( ) A 根结点无左子树 B 根结点无右子树 C 只有根结点的二叉树或非叶子结点只有左子树的二叉树 D 只有根结点的二叉树或非叶子结点只有右子树的二叉树 18 下列选项中不属于视频文件格式的是( ) A TXT B AV

如何用天天模拟器做调试

声明: 本人菜鸟一枚, 本博客是本人自学的内容, 适用于初学者, 不喜勿喷, 谢谢大家 在cmd中打命令:adb connect 127.0.0.1:6555 其中6555是天天模拟器的端口

道阻且长,行则将至——记累计跑步1000公里

2017 年开始 Keep 软件记录跑步,确切的说是工作好多年之后正式开始跑步。 在跑步累计 100 公里的时候,当时定了个小目标:1000 公里。 https://mp.weixin.qq.com/s/_QqLHwiR659obLSQs2ZJnw 没想到,这一晃过去了 7 年,就在今天 2024年8月27日,累计跑量突破 1000 公里。 对于一些马拉松爱好者、经常跑步的跑友来说,这不值一

信息学奥赛初赛天天练-76-NOIP2015普及组-基础题1-计算机存储、硬件系统、操作系统、进制转换、二进制加法

NOIP 2016 普及组 基础题1 1 1MB 等于 ( ) A 10000 字节 B 1024 字节 C 1000×1000 字节 D 1024×1024 字节 2 在 PC 机中,PENTIUM(奔腾)、酷睿、赛扬等 是指( ) A 生产厂家名称 B 硬盘的型号 C CPU 的型号 D 显示器的型号 3 操作系统的作用是( ) A 把源程序译成目标程序 B 便于进行数据管理 C 控制和

跑步为什么是逆时针

不管是小时候操场跑步或是奥运会田径比赛,甚至是滑冰比赛,它们有一个共同点就是围绕比赛场地逆时针旋转,向左转弯。 那为什么很少见到跑步时往相反的顺时针跑呢? 在跑步的方向上之所以很少有特立独行,是因为国际上有这么一项规定。 在早期的奥运会中,田径比赛中长跑是在一条长为192.27m的直线上来回折返,并没有逆时针和顺时针一说。 后来的现代奥运会,绕圈跑的方向最初实际上是顺时针跑的,比如1896

信息学奥赛初赛天天练-71-NOIP2016普及组-基础题2-进制转换、二进制转八进制、八进制转二进制、二叉树数组存储、寻址空间

NOIP 2016 普及组 基础题2 4 以下不是 CPU 生产厂商的是( ) A Intel B AMD C Microsoft D IBM 8 与二进制小数 0.1相等的八进制数是( ) A 0.8 B 0.4 C 0.2 D 0.1 9 以下是 32 位机器和 64 位机器的区别是( ) A 显示器不同 B 硬盘大小不同 C 寻址空间不同 D 输入法不同 11一棵二叉树如右图所示,若