[Noip2016]天天爱跑步 LCA+DFS
[Noip2016]天天爱跑步
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
题解:一年前多的题了,不过现在再做的话已经不是那个难度了。
想法有点古怪,直接上做法吧:
对于玩家a->b,设a,b的lca是c,路径长度是len,那么路径可以拆成2半,如果观察员i想看到第一半,那么要求dep[a]-dep[i]=w[i]->dep[a]=dep[i]+w[i],且i是a的祖先;如果i想看到第二半,那么要求len-(dep[b]-dep[i])=w[i]->len-dep[b]=w[i]-dep[i],且i是b的祖先。当然,还有一个要求,就是i在c的子树中,但是我们先不考虑这个。那么做法如下:
在DFS访问到x时,先记录之前有多少点的dep[a]=dep[x]+w[x]以及len-dep[b]=w[x]-dep[x](用桶即可),记为ans1,然后遍历x的子树,遍历结束后,将x位置的玩家的dep[a]以及len-dep[b]加入到桶中,再查询此时有多少点的dep[a]=dep[x]+w[x]以及len-dep[b]=w[x]-dep[x],记为ans2,那么ans2-ans1就是x的答案。
但是如果考虑到i在c的子树中这个条件呢?也好办,只需要在c和c的父亲中加入dep[a]和len-dep[b],并且权值都是-1即可。
如果用tarjan求LCA,则时间复杂度是O(n)的,但是我懒啊~
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int maxn=300010;
vector<int> v1[maxn],v2[maxn];
int n,m,cnt;
int head[maxn],to[maxn<<1],next[maxn<<1],w[maxn],dep[maxn],Log[maxn],fa[20][maxn];
int s1[maxn],s2[maxn<<1],ans[maxn];
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
void dfs1(int x)
{
for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[0][x])
fa[0][to[i]]=x,dep[to[i]]=dep[x]+1,dfs1(to[i]);
}
inline int lca(int a,int b)
{
if(dep[a]<dep[b]) swap(a,b);
int i;
for(i=Log[dep[a]-dep[b]];i>=0;i--) if(dep[fa[i][a]]>=dep[b]) a=fa[i][a];
if(a==b) return a;
for(i=Log[dep[a]];i>=0;i--) if(fa[i][a]!=fa[i][b]) a=fa[i][a],b=fa[i][b];
return fa[0][a];
}
void dfs2(int x)
{
int i;
ans[x]-=s1[dep[x]+w[x]]+s2[w[x]-dep[x]+n];
for(i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[0][x]) dfs2(to[i]);
for(i=0;i<(int)v1[x].size();i++)
{
if(v1[x][i]>0) s1[v1[x][i]]++;
else s1[-v1[x][i]]--;
}
for(i=0;i<(int)v2[x].size();i++)
{
if(v2[x][i]>0) s2[v2[x][i]]++;
else s2[-v2[x][i]]--;
}
ans[x]+=s1[dep[x]+w[x]]+s2[w[x]-dep[x]+n];
}
inline void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
int main()
{
n=rd(),m=rd();
int i,j,a,b,c,d;
memset(head,-1,sizeof(head));
for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
for(i=1;i<=n;i++) w[i]=rd();
dep[1]=1,dfs1(1);
for(i=2;i<=n;i++) Log[i]=Log[i>>1]+1;
for(j=1;(1<<j)<=n;j++) for(i=1;i<=n;i++) fa[j][i]=fa[j-1][fa[j-1][i]];
for(i=1;i<=m;i++)
{
a=rd(),b=rd(),c=lca(a,b),d=dep[a]+dep[b]-2*dep[c];
v1[a].push_back(dep[a]),v1[fa[0][c]].push_back(-dep[a]);
v2[b].push_back(d-dep[b]+n),v2[c].push_back(-(d-dep[b]+n));
}
dfs2(1);
for(i=1;i<n;i++) printf("%d ",ans[i]);
printf("%d",ans[n]);
return 0;
}
[Noip2016]天天爱跑步 LCA+DFS的更多相关文章
- [NOIP2016] 天天爱跑步 桶 + DFS
---题面--- 题解: 很久以前就想写了,一直没敢做,,,不过今天写完没怎么调就过了还是很开心的. 首先我们观察到跑步的人数是很多的,要一条一条的遍历显然是无法承受的,因此我们要考虑更加优美的方法. ...
- luogu1600 [NOIp2016]天天爱跑步 (tarjanLca+dfs)
经过部分分的提示,我们可以把一条路径切成s到lca 和lca到t的链 这样就分为向上的链和向下的链,我们分开考虑: 向上:如果某一个链i可以对点x产生贡献,那么有deep[x]+w[x]=deep[S ...
- [NOIp2016]天天爱跑步 线段树合并
[NOIp2016]天天爱跑步 LG传送门 作为一道被毒瘤出题人们玩坏了的NOIp经典题,我们先不看毒瘤的"动态爱跑步"和"天天爱仙人掌",回归一下本来的味道. ...
- 【LG1600】[NOIP2016]天天爱跑步
[LG1600][NOIP2016]天天爱跑步 题面 洛谷 题解 考虑一条路径\(S\rightarrow T\)是如何给一个观测点\(x\)造成贡献的, 一种是从\(x\)的子树内出来,另外一种是从 ...
- BZOJ 4719--天天爱跑步(LCA&差分)
4719: [Noip2016]天天爱跑步 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1464 Solved: 490[Submit][Stat ...
- NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】
题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn个 ...
- UOJ261 【NOIP2016】天天爱跑步 LCA+动态开点线段树
UOJ261 [NOIP2016]天天爱跑步 Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.天天爱跑步是一个养成类游戏,需要玩家每天按时上线, ...
- [luogu]P1600 天天爱跑步[LCA]
[luogu]P1600 [NOIP 2016]天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上 ...
- BZOJ4719 [Noip2016]天天爱跑步
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
随机推荐
- php中一些函数的用法
addslashes() 定义和用法 addslashes() 函数返回在预定义字符之前添加反斜杠的字符串. 预定义字符是: 单引号(') 双引号(") 反斜杠(\) NULL 提示:该函数 ...
- [转]SQL Server 性能调优(cpu)
研究cpu压力工具 perfom SQL跟踪 性能视图 cpu相关的wait event Signal wait time SOS_SCHEDULER_YIELD等待 CXPACKET等待 CME ...
- C++中的INL(转)
inl 文件是内联函数的源文件. 内联函数通常在c++头文件中实现,但有的时候内联函数较多或者出于一些别的考虑(使头文件看起来更简洁等), 往往会将这部分具体定义的代码添加到INL文件中,然后在该头文 ...
- applicationContext.xml 文件头报错Referenced file contains errors
问题如下:原先运行正常的项目,突然在applicationContext.xml 文件头报错 内容:Referenced file contains errors (http://www.spring ...
- MYSQL版查询分页存储过程
/*--名称:MYSQL版查询分页存储过程 --输入参数:@fields -- 要查询的字段用逗号隔开--输入参数:@tables -- 要查询的表--输入参数:@where -- 查询条件--输入参 ...
- mysql无法启动ERROR! MySQL is running but PID file could not be found ?
转载于:http://blog.csdn.net/wuzhilon88/article/details/17616635 第一种方法:可能是硬盘满了,清理下垃圾文件. 第二种: 查看下数据库运行状态 ...
- rac_安装软件时报版本号过高问题
原创作品,出自 "深蓝的blog" 博客.欢迎转载,转载时请务必注明下面出处,否则追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlo ...
- Atitit. atiJavaExConverter4js 新的特性
Atitit. atiJavaExConverter4js 新的特性 1.1. V1新特性1 1.2. V2 新特性1 2. Keyword1 3. Catch1 4. Convert n Thro ...
- Python模块学习之fabric
fabric是一个运维经常使用到的一个模块.但是我在python3环境下安装fabric就遇到了坑! 安装包名称是fabric3而不是fabric! pip install fabric3 利用fab ...
- MyEclipse 2013安装后要做的几件事
一.Myeclipse 2013修改字体 MyEclipse 2013是基于Eclipse3.7内核,但在Eclipse的Preferences-〉general-〉 Appearance->C ...