[NOIP]2016天天爱跑步
[NOIP]2016天天爱跑步
标签: LCA 树上差分 NOIP
Description
小C同学认为跑步非常有趣,于是决定制作一款叫做《天天爱跑步》的游戏。《天天爱跑步》是一个养成类游戏,需要玩家每天按时上线,完成打卡任务。
这个游戏的地图可以看作一棵包含n个结点和n-1条边的树,每条边连接两个结点,且任意两个结点存在一条路径互相可达。树上结点编号为从1到n的连续正整数。
现在有m个玩家,第i个玩家的起点为Si,终点为Ti。每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发,以每秒跑一条边的速度,不间断地沿着最短路径向着自己的终点跑去,跑到终点后该玩家就算完成了打卡任务。(由于地图是一棵树,所以每个人的路径是唯一的)
Input
第一行有两个整数n和m。其中n代表树的结点数量,同时也是观察员的数量,m代表玩家的数量。
接下来n-1行每行两个整数u和v,表示结点u到结点v有一条边。
接下来一行n个整数,其中第j个整数为Wj,表示结点j出现观察员的时间。
接下来m行,每行两个整数Si和Ti,表示一个玩家的起点和终点。
对于所有的数据,保证1≤Si,Ti≤n,0≤ Wj ≤n。
Output
输出1行n个整数,第j个整数表示结点j的观察员可以观察到多少人。
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
Hint
提示:
对于1号点,W1=0,故只有起点为1号点的玩家才会被观察到,所以玩家1和玩家2被观察到,共2人被观察到。
对于2号点,没有玩家在第2秒时在此结点,共0人被观察到。
对于3号点,没有玩家在第5秒时在此结点,共0人被观察到。
对于4号点,玩家1被观察到,共1人被观察到。
对于5号点,玩家2被观察到,共1人被观察到。
对于6号点,玩家3被观察到,共1人被观察到。
Pic
如果你的程序需要用到较大的栈空间(这通常意味着需要较深层数的递归),请务必仔细阅读选手目录下的文档running/stackpdf,以了解在最终评测时栈空间的限制与在当前工作环境下调整栈空间限制的方法。
题解
- 对于一个玩家,他的路径我们可以拆成两段。分别是u->lca,lca->v。对于每一个观察者x,如果deep[x]+w[x]deep[u]时,u->lca的这段路径可能会更新答案。同理,deep[x]-w[x]deep[v]-dis(u,v)时,lca->v的这段路径也有可能更新答案。
- 我们只考虑u->lca,只有当x在u->lca上时,答案才会被更新。我们就很难统计。不过我们可以利用差分的思想,把这条路径拆成u->root(贡献为1),fa[lca]->root(贡献为-1),就容易统计一些了。
- 然后我们对树进行dfs,在dfs的过程中,对每一个子树的根u来说,遍历子树,再加上自己这个点的值,然后计算这个点被访问的次数,相当于求一遍前缀和,只是加上了自己所有子树的值。
Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(int i=start[(a)];i;i=e[i].next)
inline int read()
{
int sum=0,p=1;char ch=getchar();
while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
if(ch=='-')p=-1,ch=getchar();
while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum*p;
}
const int maxn=3e5+20;
struct node {
int v,next;
};
node e[maxn*2];
int cnt,start[maxn];
int n,m;
void addedge(int u,int v)
{
e[++cnt]={v,start[u]};
start[u]=cnt;
}
int deep[maxn],p[maxn][21];
void dfs(int u,int fa)
{
p[u][0]=fa;
EREP(i,u)
{
int v=e[i].v;
if(v==fa)continue;
deep[v]=deep[u]+1;
dfs(v,u);
}
}
int lca(int u,int v)
{
if(deep[u]<deep[v])swap(u,v);
DREP(i,20,0)if(p[u][i]!=-1 &&deep[p[u][i]]>=deep[v])u=p[u][i];
if(u==v)return u;
DREP(i,20,0)if(p[u][i]!=-1 && p[u][i]!=p[v][i])u=p[u][i],v=p[v][i];
return p[u][0];
}
struct player {
int t,w,next,id;
};
player ed[maxn*4];
int st[maxn],cn;
void add(int u,int t,int w,int idx)
{
ed[++cn]={t,w,st[u],idx};
st[u]=cn;
}
int A[maxn],B[maxn];
int ans[maxn];
int CntA[maxn*2],CntB[maxn*2];
void dfs1(int u,int fa)
{
int la=CntA[A[u]];
int lb=CntB[B[u]+maxn];
for(int i=st[u];i;i=ed[i].next)
{
int x=ed[i].t;
if(ed[i].id==1)
{
CntA[x]+=ed[i].w;
}else
{
CntB[x+maxn]+=ed[i].w;
}
}
EREP(i,u)
{
int v=e[i].v;
if(v==fa)continue;
dfs1(v,u);
}
int na=CntA[A[u]];
int nb=CntB[B[u]+maxn];
ans[u]+=(na-la)+(nb-lb);
}
void init()
{
n=read();m=read();
REP(i,1,n-1)
{
int u=read(),v=read();
addedge(u,v);
addedge(v,u);
}
deep[1]=1;
dfs(1,0);
REP(i,1,n)
{
int w=read();
A[i]=deep[i]+w;
B[i]=deep[i]-w;
}
REP(j,1,20)REP(i,1,n)p[i][j]=p[p[i][j-1]][j-1];
REP(i,1,m)
{
int u=read(),v=read(),Lca=lca(u,v);
int len=deep[u]+deep[v]-2*deep[Lca];//点用链表储存,方便调用
add(u,deep[u],1,1);
add(p[Lca][0],deep[u],-1,1);
add(v,deep[v]-len,1,2);
add(Lca,deep[v]-len,-1,2);
}
dfs1(1,0);
REP(i,1,n)
cout<<ans[i]<<" ";
}
int main()
{
freopen("input.in","r",stdin);
freopen("output.out","w",stdout);
init();
return 0;
}
[NOIP]2016天天爱跑步的更多相关文章
- NOIP 2016 天天爱跑步 80分暴力
题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 个结点 ...
- [NOIp 2016]天天爱跑步
Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图 ...
- Noip 2016 天天爱跑步 题解
[NOIP2016]天天爱跑步 时间限制:2 s 内存限制:512 MB [题目描述] 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是 ...
- NOIP 2016 天天爱跑步 (luogu 1600 & uoj 261) - 线段树
题目传送门 传送点I 传送点II 题目大意 (此题目不需要大意,我认为它已经很简洁了) 显然线段树合并(我也不知道哪来这么多显然) 考虑将每条路径拆成两条路径 s -> lca 和 t -> ...
- 【NOIP】提高组2016 天天爱跑步
[题意]n个点的树,有m个人同时开始走链,每一步花一秒,n个点都有观察员在ai秒观察,求每个观察员观察到的人数. [算法]树上差分(主席树||线段树合并) [题解]一个人的走链可以拆成u-lca和lc ...
- [luogu]P1600 天天爱跑步[LCA]
[luogu]P1600 [NOIP 2016]天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上 ...
- 【NOIP 2016】Day1 T2 天天爱跑步
Problem Description 小 C 同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任 ...
- NOIP提高组2016 D1T2 【天天爱跑步】
码了一个下午加一个晚上吧...... 题目描述: 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成 ...
- [NOIP 2016D2T2/Luogu P1600] 天天爱跑步 (LCA+差分)
待填坑 Code //Luogu P1600 天天爱跑步 //Apr,4th,2018 //树上差分+LCA #include<iostream> #include<cstdio&g ...
随机推荐
- springboot之fastjson
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifac ...
- CSDN博客测试目录
经常写博客,但是一般没怎么注意些目录,最近看别人写的博客都有目录,所以我也想在以后写好目录,这样子也方便阅读. 这里就写一个实验: 这里一级目录 这里是一级目录下的文本.林肯公园 这里是1.1目录 这 ...
- maven系列--maven常用命令
下一篇博客我会讲解用eclipse的m2插件来使用maven,这里先大概的了解下maven常用的命令.之后我在详细整理maven的生命周期,到时候会细致的讲解下这些指令应该要怎么使,maven都帮我们 ...
- mavean的依赖传递和排除依赖
三个mavean项目 A .B. C 如果B依赖A(A先执行clean package命令) 那么B得pom.xml文件里面就写 <dependency> <groupId> ...
- 03_HTML Canvas第一天
视频来源:麦子学院 讲师:刘慧涛 w3cshool之HTML5画布:http://www.w3school.com.cn/html5/html_5_canvas.asphtml5 canvas参考手册 ...
- execl列数据成等差递增递减
如上图若想以10,20,30...这样递增: 1).首先需选中10,20所在的单元格,鼠标移至20所在的单元格右下角 2).此时会出现一个十字"十"符号,点击直向下拖动至某个地方, ...
- python使用上下文管理器实现sqlite3事务机制
如题,本文记录如何使用python上下文管理器的方式管理sqlite3的句柄创建和释放以及事务机制. 1.python上下文管理(with) python上下文管理(context),解决的是这样一类 ...
- svn基本操作和图标介绍
注意事项: .svn这个隐藏目录记录着两项关键信息:工作文件的基准版本和一个本地副本最后更新的时间戳,千万不要手动修改或者删除这个.svn隐藏目录和里面的文件!!,否则将会导致你本地的工作拷贝( ...
- 异常检测算法:Isolation Forest
iForest (Isolation Forest)是由Liu et al. [1] 提出来的基于二叉树的ensemble异常检测算法,具有效果好.训练快(线性复杂度)等特点. 1. 前言 iFore ...
- thinkpadE470 win10安装虚拟机时出现‘intel VT-x’处于禁用状态 无法执行64位操作系统
上图为安装虚拟机时弹出的问题. 解决办法: 本人电脑型号为thinkpadE470.遇到此问题查阅了很多,都是针对一般电脑的.折腾了好一会儿.故特写一篇针对此型号的. 1.重启计算机,一开始出现联想标 ...