[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/转 ...
随机推荐
- Win7如何改变用户文件夹位置
现在装WIN7后第一件就是改变用户账户文件夹位置..因为里面存着一些软件的设定和信息等..不必要每次装后都手动改一次.. 已前用优化大师改.太麻烦.也不稳定有时有些目录不能完全改过来.. 通过命令mk ...
- Windows COM Surrogate 已停止工作怎么办
已解决 如何解决"COM Surrogate 已停止工作"问题 悬赏分:15 - 解决时间:2008-7-6 16:55 Vista系统,经常出现这个提示框,烦人. 我试了网上有关 ...
- Nginx Errors: upstream response cache error
Nginx Errors upstream response cache error *2470578 an upstream response is buffered to a temporary ...
- centos7单机版安装hbase
1.首先安装jdk1.8 yum install java-1.8.0-openjdk* -y 2.下载hbase 地址:http://mirrors.shuosc.org/apache/hbase/ ...
- 在iis6里使用没有扩展名的mvc
这2天mvc第二个预览终于出来了.赶紧拿过来测试.在装了3.5的虚拟主机上运行正常.应该已经可以到能正常使用的阶段了.不过我前面一篇翻译的文章中说到,如果使用的是iis6的话就只能忍气吞声的使用带扩展 ...
- 服务器中很多的CLOSE_WAIT
服务器中很多的CLOSE_WAIT,请教各位大虾!!!!!!!!!最近遇到一个问题,工程在LINUX服务器上面跑起来了以后,运行一段时间 就有很多的CLOSE_WAIT链接,多了之后,网站就访问不了了 ...
- 21. Merge Two Sorted Lists【easy】
21. Merge Two Sorted Lists[easy] Merge two sorted linked lists and return it as a new list. The new ...
- 75. Find Peak Element 【medium】
75. Find Peak Element [medium] There is an integer array which has the following features: The numbe ...
- awk 数组
Arrays Arrays are subscripted with an expression between square brackets ([ and ]). If the ...
- __attribute__系列之aligned
__attribute__的属性aligned,作用是为了设置字节对齐. aligned是对 变量和结构体进行 字节对齐的属性设置. 通过aligned属性设置(aligned(对齐字节数)),可以显 ...