题目描述

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

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

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

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

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

输入输出格式

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

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

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

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

对于所有的数据,保证 。

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

输入输出样例

输入样例#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
输出样例#1:
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
输出样例#2:
1 2 1 0 1

题解

这题部分分很多,水分可以有80分
从链的那部分分入手
设f[i]表示第i个点作为出发点的数量
那么某条从x到y路径在f值中的对应位置就是f[x]
那么对于跑的路即x~y有两种可能,一种是往左,一种是往右
考虑往右的情况
记录一下有多少路径从每个点开始,在每个点结束的路径的起始点
那么在枚举点的时候,算答案之前把从这个点开始的路径在f值中的对应位置+1,算完答案后,把在这个点结束的路径在f值对应的位置-1
往左的情况相同,倒着搜就行了

对于一棵树,你想到了什么?
树链剖分!!
那么f[i]就是深度为i的点作为出发点的数量
那么某条从x到y路径在f值中的对应位置就是f[deep[x]]
然后把一条在树上的路径变成一堆路径,在分成的每个路径的开始和结束位置向上面一样打上标记
算答案的时候就不是枚举点,而是枚举dfs序,再把答案加在对应的点上
可以保证时间复杂度为O(nlog2(m))O(nlog_2(m))
但是常数……
需要卡常

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define N 301000
using namespace std;
int w[N],last[N*10],next[N*10],to[N*10],tot=0,n,m,dfn[N],fa[N],son[N],top[N],size[N],g[N+N+N],deep[N],ans[N];
int ls[N*10],nx[N*10],dt[N*10],to1=0,la[N*10],ne[N*10],da[N*10],to2=0,yl[N];
int ls2[N*10],nx2[N*10],dt2[N*10],to3=0,la2[N*10],ne2[N*10],da2[N*10],to4=0;
void putin(int x,int y)
{next[++tot]=last[x];last[x]=tot;to[tot]=y;
}
void put1(int x,int y)
{nx[++to1]=ls[x];ls[x]=to1;dt[to1]=y;
}
void put2(int x,int y)
{ne[++to2]=la[x];la[x]=to2;da[to2]=y;
}
void put3(int x,int y)
{nx2[++to3]=ls2[x];ls2[x]=to3;dt2[to3]=y;
}
void put4(int x,int y)
{ne2[++to4]=la2[x];la2[x]=to4;da2[to4]=y;
}
void dg1(int x)
{size[x]=1;int mx=0;for(int i=last[x];i;i=next[i]){if(size[to[i]]) continue;fa[to[i]]=x;deep[to[i]]=deep[x]+1;dg1(to[i]);size[x]+=size[to[i]];if(size[to[i]]>size[mx]) mx=to[i];}son[x]=mx;
}
void dg2(int x)
{dfn[x]=++tot;yl[tot]=x;if(son[x]) top[son[x]]=top[x],dg2(son[x]);for(int i=last[x];i;i=next[i]){if(dfn[to[i]]) continue;top[to[i]]=to[i];dg2(to[i]);}
}
int lca(int x,int y)
{int f1=top[x],f2=top[y];for(;f1!=f2;) if(deep[f1]>=deep[f2]) x=fa[f1],f1=top[x];else y=fa[f2],f2=top[y];if(deep[x]<deep[y]) return x;else return y;
}
void lct(int x,int y)
{int z=lca(x,y),bz=1;int jy1=deep[x],jy2=deep[z]-deep[x]+deep[z];int f1=top[x],f2=top[y];for(;f1!=f2;){if(deep[f1]>=deep[f2]) put1(dfn[x],jy1),put2(dfn[f1],jy1),x=fa[f1];else put3(dfn[f2],jy2),put4(dfn[y],jy2),y=fa[f2];f1=top[x],f2=top[y];}if(deep[x]<deep[y]) put3(dfn[x],jy2),put4(dfn[y],jy2);else put1(dfn[x],jy1),put2(dfn[y],jy1);
}
int main()
{freopen("running.in","r",stdin);freopen("running.out","w",stdout);scanf("%d%d",&n,&m);int x,y;fo(i,1,n-1){scanf("%d%d",&x,&y);putin(x,y);putin(y,x);}fo(i,1,n) scanf("%d",&w[i]);tot=0;deep[1]=1;top[1]=1;dg1(1);dg2(1);fo(i,1,m){int x,y;scanf("%d%d",&x,&y);lct(x,y);}fo(i,1,n){for(int k=ls2[i];k;k=nx2[k]) g[dt2[k]+N]++;ans[yl[i]]+=g[deep[yl[i]]-w[yl[i]]+N];for(int k=la2[i];k;k=ne2[k]) g[da2[k]+N]--;}fd(i,n,1){for(int k=ls[i];k;k=nx[k]) g[dt[k]+N]++;ans[yl[i]]+=g[deep[yl[i]]+w[yl[i]]+N];for(int k=la[i];k;k=ne[k]) g[da[k]+N]--;}fo(i,1,n) printf("%d ",ans[i]);fclose(stdin);fclose(stdout);return 0;
}

NOIP2016提高组 第一天第二题 天天爱跑步running 题解相关推荐

  1. NOIP 2016 提高组 Day 1 第二题 天天爱跑步

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

  2. NOI Online #2 提高组 第一题:涂色游戏

    NOI Online #2 提高组 第一题:涂色游戏 前言 题目 解析 代码 前言 呦呵,这道题我竟然爆零了 而且我的暴力dfs死循环了!\bold{\Large\xcancel\text{而且我的暴 ...

  3. 【NOIP2016提高组】天天爱跑步

    题目背景 NOIP2016 提高组 Day1 T2 题目描述 小 C 同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每 ...

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

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

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

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

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

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

  7. 第一章第二题(显示五条消息)(Display five messages)

    第一章第二题(显示五条消息)(Display five messages) 1.2(显示五条消息)编写程序,显示 Welcome to Java 五次. 1.2 (Display five messa ...

  8. 涂色游戏color(【CCF】NOI Online 能力测试2 提高组第一题 )

    子序列问题sequence([CCF]NOI Online能力测试2 提高组第二题 ) 游戏match([CCF]NOI Online能力测试2 提高组第三题 ) 题目背景 1s 256M 题目描述 ...

  9. NOIP2016 提高组 解题报告

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

最新文章

  1. 关于工作流引擎的设计讨论
  2. lvm创建逻辑卷简单过程
  3. 【Java 虚拟机原理】Class 字节码二进制文件分析 一 ( 字节码文件附加信息 | 魔数 | 次版本号 | 主版本号 | 常量池个数 )
  4. 计算机考博哪个学校好考,管理学博士哪个学校好考
  5. 手机访问服务器中的数据库文件,手机连接服务器数据库文件在哪里
  6. 边工作边刷题:70天一遍leetcode: day 11-1
  7. ERP项目实施记录08
  8. 文件搜索工具Listary中文版快速上手使用教程
  9. Flutter 使用 GetIt 容器将新增和编辑后的数据同步更新到列表
  10. 苹果台式电脑怎么使用计算机,MAC电脑连接台式电脑显示器怎么操作
  11. linux终端删除文件命令_如何在Linux终端中删除文件和目录
  12. 微信又因夜间模式上热搜,我们又成为了谣言的传播者
  13. 关于YouTub视频广告格式
  14. 十月,你好。余杭,巴比特来了!
  15. 初识CornerNet
  16. Mysql Schema优化
  17. 一度智信:电商网店推广技巧分享
  18. 推荐一款IDEA 快捷键 自动提示插件
  19. Beam Search与Prefix Beam Search的理解与python实现
  20. 自己留着用的 .net 图片水印 方法

热门文章

  1. 温莎计算机应用硕士是针对国际学生的吗,留学温莎大学
  2. 自己用的停用词(2955个)
  3. html 水平柱形图,CSS实现柱形图效果的代码示例
  4. 困住黑猫 html5,百变大侦探白狐凶手是谁 百变大侦探白狐密室密码
  5. Consul + fabio 实现自动服务发现、负载均衡 - DockOne.io
  6. 地图学的基础知识_天文坐标系_大地坐标系_地心坐标系及其相关概念
  7. 专访 | 宋星 10 年启示录:数字营销如何觐见下一个 10 年?
  8. 【MySQL】DML,DQL
  9. 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛 G-旋转矩阵
  10. 请编写一个程序,输入一个由小写字母和其他字符构成的序列字符串保存在tt中,统计“a”到“z”26个字母各自出现的次数,并依次保存在pp数组中,并输出pp数组内容。