题目大意:
  有一棵n个点的树,每个点上有一个摄像头会在第w[i]秒拍照。
  有m个人再树上跑,第i个人沿着s[i]到t[i]的路径跑,每秒钟跑一条边。
  跑到t[i]的下一秒,人就会消失。
  问每个摄像头会拍下几个人。

思路:
  首先很显然是要求LCA的。
  求完LCA怎么办?
  我们可以用树上差分的方法分别维护向上、向下的链。
  每一条路径,我们可以在s,t,lca,par[lca]上分别打标记。
  s +dep[s]
  t +dep[t]-len
  lca -dep[s]
  par[lca] +len-dep[t]
  其中有一些是向上走的链、有一些是向下走的链,因此我们还需要将它们区分开来。
  一个点x满足条件当且仅当x在s到lca的路上且dep[x]-dep[s]=w[x],
  或者x在lca到t的路上且dep[lca]-dep[s]+deo[lca]-dep[x]=w[x]。
  最后从根节点DFS统计一下,访问到x结点就把对应的标记加进去,ans[x]=统计完子树后的答案-统计之前的答案。
  另外注意dep[t]-len可能会是负的,因此我们可以将它们整体往右移一些位置。

 #include<cstdio>
#include<cctype>
#include<vector>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int N=,logN=;
std::vector<int> e[N];
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
int w[N],dep[N],anc[N][logN];
inline int log2(const float &x) {
return ((unsigned&)x>>&)-;
}
void dfs(const int &x,const int &par) {
dep[x]=dep[par]+;
anc[x][]=par;
for(register int i=;i<=log2(dep[x]);i++) {
anc[x][i]=anc[anc[x][i-]][i-];
}
for(register unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==par) continue;
dfs(y,x);
}
}
inline int lca(int x,int y) {
if(dep[x]<dep[y]) std::swap(x,y);
for(register int i=log2(dep[x]-dep[y]);i>=;i--) {
if(dep[anc[x][i]]>=dep[y]) {
x=anc[x][i];
}
}
if(x==y) return x;
for(register int i=log2(dep[x]);i>=;i--) {
if(anc[x][i]!=anc[y][i]) {
x=anc[x][i];
y=anc[y][i];
}
}
return anc[x][];
}
struct Tag {
bool type;
int val,sgn;
};
std::vector<Tag> tag[N];
int ans[N];
int cnt1[N<<],cnt2[N<<];
void stat(const int &x) {
const int tmp=cnt1[dep[x]+w[x]]+cnt2[dep[x]-w[x]+(N<<)];
for(register unsigned i=;i<tag[x].size();i++) {
const Tag &t=tag[x][i];
(t.type?cnt1:cnt2)[t.val]+=t.sgn;
}
for(unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==anc[x][]) continue;
stat(y);
}
ans[x]=cnt1[dep[x]+w[x]]+cnt2[dep[x]-w[x]+(N<<)]-tmp;
}
int main() {
const int n=getint(),m=getint();
for(register int i=;i<n;i++) {
add_edge(getint(),getint());
}
for(register int i=;i<=n;i++) {
w[i]=getint();
}
dfs(,);
for(register int i=;i<m;i++) {
const int s=getint(),t=getint(),p=lca(s,t),len=dep[s]+dep[t]-(dep[p]<<);
tag[s].push_back((Tag){,dep[s],});
tag[t].push_back((Tag){,dep[t]-len+(N<<),});
tag[p].push_back((Tag){,dep[s],-});
tag[anc[p][]].push_back((Tag){,dep[t]-len+(N<<),-});
}
stat();
for(register int i=;i<n;i++) {
printf("%d ",ans[i]);
}
printf("%d",ans[n]);
return ;
}

[NOIp2016提高组]天天爱跑步的更多相关文章

  1. P1600 [NOIP2016 提高组] 天天爱跑步 (树上差分)

    对于一条路径,s-t,位于该路径上的观察员能观察到运动员当且仅当以下两种情况成立:(d[ ]表示节点深度) 1.观察员x在s-lca(s,t)上时,满足d[s]=d[x]+w[x]就能观察到,所以我们 ...

  2. NOIP2016提高组解题报告

    NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合

  3. 【题解】NOIP2016提高组 复赛

    [题解]NOIP2016提高组 复赛 传送门: 玩具谜题 \(\text{[P1563]}\) 天天爱跑步 \(\text{[P1600]}\) 换教室 \(\text{[P1850]}\) 组合数问 ...

  4. 【题解】NOIP2016 提高组 简要题解

    [题解]NOIP2016 提高组 简要题解 玩具迷题(送分) 用异或实现 //@winlere #include<iostream> #include<cstdio> #inc ...

  5. [NOIP2016 DAY1 T2]天天爱跑步-[差分+线段树合并][解题报告]

    [NOIP2016 DAY1 T2]天天爱跑步 题面: B[NOIP2016 DAY1]天天爱跑步 时间限制 : - MS 空间限制 : 565536 KB 评测说明 : 2s Description ...

  6. BZOJ4719[NOIP2016提高组Day1T2] 天天爱跑步

    #261. [NOIP2016]天天爱跑步 描述 提交 自定义测试 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家 ...

  7. 【NOIP2016提高组复赛day2】天天爱跑步

    题目 小 C 同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏. <天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一棵 ...

  8. Luogu P1600[NOIP2016]day1 T2天天爱跑步

    号称是noip2016最恶心的题 基本上用了一天来搞明白+给sy讲明白(可能还没讲明白 具体思路是真的不想写了(快吐了 如果要看,参见洛谷P1600 天天爱跑步--题解 虽然这样不好但我真的不想写了 ...

  9. [日记&做题记录]-Noip2016提高组复赛 倒数十天

    写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...

随机推荐

  1. Python面向对象学习2(面向对象的语法和特性,待更新)

    上一个内容我们介绍了面向对象和面向对象场景现在我们来学习下语法和特性 1,面向对象基本语法: # -*- coding:utf-8 -*- # Author: Colin Yao class Dog( ...

  2. 抓其根本(一)(hdu2710 Max Factor 素数 最大公约数 最小公倍数.....)

    素数判断: 一.根据素数定义,该数除了1和它本身以外不再有其他的因数. 详见代码. int prime() { ; i*i<=n; i++) { ) //不是素数 ; //返回1 } ; //是 ...

  3. Java多线程学习(二)synchronized关键字(1)

    转载请备注地址: https://blog.csdn.net/qq_34337272/article/details/79655194 Java多线程学习(二)将分为两篇文章介绍synchronize ...

  4. python写一段脚本代码自动完成输入(目录下的所有)文件的数据替换(修改数据和替换数据都是输入的)【转】

    转自:http://blog.csdn.net/lixiaojie1012/article/details/23628129 初次尝试python语言,感觉用着真舒服,简单明了,库函数一调用就OK了 ...

  5. C高级 框架开发中红黑树结构

    引言  -- 红黑树历史 红黑树是数据结构学习中一道卡. 底层库容器中必不可少的算法. 历经各种实战运用,性能有保障. 同样红黑树不好理解, 就算理解了, 代码也不好写. 就算写了, 工程库也难构建. ...

  6. C基础 mariadb处理简单案例

    引言 MariaDB 是一款灰常不错开源数据库. 这里直接用它来解决业务问题. 业务需求: 现在数据库中表示按照天分表的. 突然我们需要按照月来处理数据. 例如输入一个玩家id, 查找这个玩家这个月内 ...

  7. STL容器之间的差异和联系

     1.vector  (连续的空间存储,可以使用[]操作符)快速的访问随机的元素,快速的在末尾插入元素,但是在序列中间的插入,删除元素要慢(涉及元素复制移动),而且如果一开始分配的空间不够的话,有一个 ...

  8. FineReport——权限分配以及自定义首页

    权限分配可以有两种方法,第一种方法是根据部门职位分配权限,第二种是根据角色分配权限: FR自带有三个JQ对象,用以保存用户名参数/角色参数/部门参数——$fr_username/$fr_authori ...

  9. [路由] -- Yii2 url地址美化与重写

    转载:http://blog.csdn.net/lmjy102/article/details/53857520

  10. django的事务

    在某些时候,你可能会在视图修改两张数据表.并且想让他们同时成功或者同时失败.这就是事务的原子性(atomicity).在django中应该怎么做呢? 详细可以参考官方文档:https://yiyibo ...