[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 ...
随机推荐
- RSync实现文件备份同步,rsync服务器
转自:http://www.cnblogs.com/itech/archive/2009/08/10/1542945.html [rsync实现网站的备份,文件的同步,不同系统的文件的同步,如果是wi ...
- nginx添加编译lua模块
一 .安装LuaJit 1.下载LuaJit # wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz 2.编译安装 # tar xzvf LuaJI ...
- requests_模拟登录知乎
如何登录知乎? 首先要分析,进行知乎验证的时候,知乎服务器需要我们提交什么数据,提交的地址.先进行几次登录尝试,通过浏览器中network中查看数据流得知,模拟登录知乎需要提供5个数据,分别是_xsr ...
- 数据流(任务并行库 TPL)
TPL 数据流库向具有高吞吐量和低滞后时间的占用大量 CPU 和 I/O 操作的应用程序的并行化和消息传递提供了基础. 它还能显式控制缓存数据的方式以及在系统中移动的方式. 为了更好地了解数据流编程模 ...
- SQL模板资源管理器,你用了吗?
SQL Server Management Studio 有个模板资源管理器,不知你用过没有?使用模板创建脚本.自定义模板等功能能大大提高你的工作效率,如果没有尝试过,赶紧去试试吧.很多时候,我们习惯 ...
- css3 box-shadow让我们实现图层阴影效果
box-shadow box-shadow: h-shadow v-shadow blur spread color inset;box-shadow:2px 2px 3px rgba(50,50,5 ...
- 几次面试后才弄懂的HashMap
本人大四,以前也开发过几个项目,Map相关集合也总用.但是从来没有研究过底层的实现,只知道杂用.结果在最开始的几次面试中一脸懵逼.认识到不足后,浅显的学习了一下,总结成一下几点.(如果写错了还望指正) ...
- CSS——类和ID选择器的区别
1.相同点,可以应用在任何元素. 2.不同点,ID选择器只能在元素里只能分别引用,不能同时引用. 如: <style type="text/css">.stress{( ...
- 面试中的DNS
DNS 当DNS客户机需要在程序中使用名称时,它会查询DNS服务器来解析该名称.客户机发送的每条查询信息包括三条信息:指定的DNS域名,指定的查询类型,DNS域名的指定类别. DNS基于UDP服务,端 ...
- H5 Canvas图像模糊解决办法
1.最近在用h5的canvas画动画,发现图像特别模糊.后来终于找到罪魁祸首是<meta name="viewport" content="width=device ...