BZOJ 4719--天天爱跑步(LCA&差分)
4719: [Noip2016]天天爱跑步
Time Limit: 40 Sec Memory Limit: 512 MB
Submit: 1464 Solved: 490
[Submit][Status][Discuss]
Description
Input
Output
输出1行N 个整数,第个整数表示结点的观察员可以观察到多少人。
Sample Input
2 3
1 2
1 4
4 5
4 6
0 2 5 1 2 3
1 5
1 3
2 6
Sample Output
HINT
题目链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=4719
Solution
刚开始学OI的时候就看过这道题。。。当时是贴代码过的。。。。
记得好像是用树链剖分。。不记得了。。反正很长。。。
现在快要noip了。。。把往年的题目拿出来看一下,算是临近noip的梳理吧。。。。。
好多废话
进入正题。。。。。
首先每个人都要走最短路径。。。马上想到LCA。。。不然还能有什么。。。
每个人分别统计显然是不行的,不过似乎可以根据特殊情况水很多分。。
于是想到差分。。
假设第 i 个人的起点为 Si ,终点为 Ti 。。LCA ( Si ,Ti ) = rt
每条线段长度都是 1 ,故路径长度与深度有关。。。
于是路径就可以分成两部分:Si -> rt 和 rt ->Ti
两条路径分开统计。。。
在向上的路径中,比如一个起点 Si ,深度为 dep [ Si ] ,
那么可以在遍历到Si的时候 U [ dep [ Si ] ] ++;
然后在到达 rt 的父亲的时候 U [ dep [ Si ] ] --; (U [ i ]表示某一方向路径的总值)
向下的路径用一样的方法。。。但这样rt 的统计会有重复。。
所以两次统计中要有一次在 rt 的时候就 U [ dep [ Si ] ] - - ;
这样就可以了,虽然分析很长但代码不是很长。。。。
注意在BZOJ上提交不能有末尾空格。。。害我PE了一发。。。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define N 400000
using namespace std;
inline int Read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,cnt=0;
int fa[N][22];
int hed[N],w[N],dep[N],ans[N],U[N],D[N<<1];
struct edge{
int r,nxt;
}e[N<<1];
struct node{
int u,w;
};
vectore1[N],e2[N<<1];
void insert(int u,int v){
e[++cnt]=(edge){v,hed[u]};hed[u]=cnt;
e[++cnt]=(edge){u,hed[v]};hed[v]=cnt;
}
void dfs1(int x,int F){
for(int i=1;(1<<i)<=dep[x];i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i=hed[x];i;i=e[i].nxt)
if(e[i].r!=F){
dep[e[i].r]=dep[x]+1;
fa[e[i].r][0]=x;
dfs1(e[i].r,x);
}
}
int lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
int d=dep[u]-dep[v];
for(int i=0;(1<<i)<=d;i++)
if((1<<i)&d)
u=fa[u][i];
if(u==v)return u;
for(int i=20;i>=0;i--){
if((1<<i)>dep[u] || fa[u][i]==fa[v][i])continue;
u=fa[u][i];v=fa[v][i];
}
return fa[u][0];
}
void dfs2(int x,int F){
ans[x]-=U[w[x]+dep[x]];
ans[x]-=D[w[x]-dep[x]+n];
for(int i=0;i<e1[x].size();i++)
U[e1[x][i].u]+=e1[x][i].w;
for(int i=0;i<e2[x].size();i++)
D[e2[x][i].u+n]+=e2[x][i].w;
for(int i=hed[x];i;i=e[i].nxt)
if(e[i].r!=F)
dfs2(e[i].r,x);
ans[x]+=U[w[x]+dep[x]]+D[w[x]-dep[x]+n];
}
int main(){
int u,v,rt;
n=Read();m=Read();
for(int i=1;i<n;i++){
u=Read();v=Read();
insert(u,v);
}
for(int i=1;i<=n;i++)
w[i]=Read();
dfs1(1,0);
for(int i=1;i<=m;i++){
u=Read();v=Read();
rt=lca(u,v);
e1[u].push_back((node){dep[u],1});
e1[rt].push_back((node){dep[u],-1});
e2[v].push_back((node){dep[u]-(dep[rt]<<1),1});
e2[fa[rt][0]].push_back((node){dep[u]-(dep[rt]<<1),-1});
}
dfs2(1,0);
for(int i=1;i<n;i++)
printf("%d ",ans[i]);
printf("%d",ans[n]);
return 0;
}
This passage is made by Iscream-2001.
BZOJ 4719--天天爱跑步(LCA&差分)的更多相关文章
- [NOIP 2016D2T2/Luogu P1600] 天天爱跑步 (LCA+差分)
待填坑 Code //Luogu P1600 天天爱跑步 //Apr,4th,2018 //树上差分+LCA #include<iostream> #include<cstdio&g ...
- [BZOJ 4719] 天天爱跑步
Link: BZOJ 4719 传送门 Solution: 感觉求LCA又有了新姿势啊:$Tarjan$离线$O(n+m)$ 每次递归返回时将子树和父节点合并,如果询问节点已访问过则LCA就是已合并的 ...
- NOIP2016 Day1 T2 天天爱跑步(树上差分,LCA)
原文链接 原题链接 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏 ...
- UOJ261 【NOIP2016】天天爱跑步 LCA+动态开点线段树
UOJ261 [NOIP2016]天天爱跑步 Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.天天爱跑步是一个养成类游戏,需要玩家每天按时上线, ...
- [Noip2016]天天爱跑步 LCA+DFS
[Noip2016]天天爱跑步 Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要玩家每天按时上线,完成打卡任 ...
- [luogu]P1600 天天爱跑步[LCA]
[luogu]P1600 [NOIP 2016]天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上 ...
- [NOIP2016]天天爱跑步(树上差分+线段树合并)
将每个人跑步的路径拆分成x->lca,lca->y两条路径分别考虑: 对于在点i的观察点,这个人(s->t)能被观察到的充要条件为: 1.直向上的路径:w[i]=dep[s]-dep ...
- NOIP2016 天天爱跑步 (树上差分+dfs)
题目大意:给你一颗树,树上每个点都有一个观察员,他们仅会在 w[i] 时刻出现,观察正在跑步的玩家 一共有m个玩家,他们分别从节点 s[i] 同时出发,以每秒跑一条边的速度,沿着到 t[i] 的唯一路 ...
- NOIP2016Day1T2天天爱跑步(LCA+桶)
据说是今年NOIP最难一题了...我还记得当时满怀期待心情点开Day1的题发现T2就不会了于是怀疑人生良久... 啊好像很多大爷都是用线段树合并写的,我怎么什么数据结构都不会啊呜呜呜... 题目大意就 ...
随机推荐
- 迷你MVVM框架 avalonjs 学习教程5、显示隐藏控制
今天的主角是ms-visible,它的效果类拟于jQuery的toggle,如果它后面跟着的表达式为真值时则显示它所在的元素,为假值时则隐藏.不过显示不是 display:none这么简单,众所周知, ...
- eval函数的使用之一
把从后台传到前端的json格式的字符串转成json success: function(data){ var json =eval("("+data+")"); ...
- clr相关名词
程序集:一个或多个类型定义文件和资源文件的集合 Native Code(本机代码): 已被编译为特定于处理器的机器码的代码. 本地代码(native code)是计算机编程(代码),编译用来运行一个特 ...
- 12. Integer to Roman (HashTable)
Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 t ...
- UNITY录制视屏解决方案 - ShareREC For Unity3D
注意buildSetting里面,AutoGraphic改成opengl es2,否则魅蓝手机上容易出现1/4屏 一.导入项目 1.到Mob官网下载ShareREC For Unity3D 的SDK包 ...
- rabbitmq的简单介绍二
上一篇博客我们没有介绍完rabbitmq,今天我们接着上一篇的博客继续介绍rabbitmq 这边的博客的内容如下 1.组播,对指定的队列设置关键词,通过关键词来控制消息的分发 2.更加细致的组播 先来 ...
- java代码实现网络远程开机
http://my.oschina.net/kingfire/blog/156764 概述 远程开机(Wake onLAN)是指通过网络实现对服务器或者pc启动运行,现在很多网卡都支持的这个功能. 其 ...
- asp.net 自定义节配置 (configSections下的section)
<configuration> <configSections> <!--.自定义一个节 CustomSection --> <section name=&q ...
- FCLK、HCLK、PCLK
一,PLL S3C2440 CPU主频可达400MHz,开发板上的外接晶振为12M,通过时钟控制逻辑的PLL(phase locked loop,锁相环电路)来倍频这个系统时钟.2440有两个P ...
- StarUML 5.0问题解决:Failed to open the model file. Invalid file format.
使用StarUML 5.0打开一个已有的文件时,如果遇到报"Failed to open the model file. Invalid file format."错误,则原因可能 ...