学弟不是说要出丧题吗》》所以我就研究了1天lca又研究了1天tj然后研究了一天天天爱跑步,终于写了出来。(最后的平均用时为240ms。。。比学弟快了1倍。。。)

题意:给你颗树,然后有m个东西在树上移动,每s移动一条边。路径为S[i]->T[i],现在求在w[i]时第i各节点上有多少个东西。

解题思路:首先,我们考虑使用lca将走过的路径拆成2半,一段为S->f(lca),一段为f(lca)->T,显然对于一个点在T时所经过他的东西数,我们是可以通过树上差分求出的,具体方法:首先讲一下从S->f的做法,考虑按深度差分,显然第i个人第0s的位置为deep[S],于是记此时差分数组中deep[S]--,这样若一个人在w[i]时经过点i,显然我们可以认为差分数组中的[deep[i]-w[i]]就可以代表了这个点的答案,但显然这是过于理想化的考虑,显然对于一个节点,其子树外的情况也会影响到这个点的数值,因而我们需要在遍历以这个节点为根的子树前先减去差分数组的值,这样就可以使得答案一定是子树内的情况了。从f->T也同样如此可以完成,这里不再赘述,具体实现请参考AC代码,注意一些细节的处理:).

AC代码:

 #include<stdio.h>
#define MN 300005
#define nt edge[i].to
struct zxy{int to,next;}edge[MN*];//链表(把多个链表都塞进去了)
int cnt,h[MN],q[MN],adh1[MN],deh1[MN],adh2[MN],deh2[MN];//各链表表头
int qans[MN],tim[MN],deep[MN],n,m,chafen[MN*],fa[MN],ans[MN],x[MN],y[MN];
bool vis[MN];
inline void ins(int *h,int x,int y){edge[++cnt].next=h[x],edge[cnt].to=y,h[x]=cnt;}//构造链表
inline int getfa(int x){return fa[x]?fa[x]=getfa(fa[x]):x;}//并查集
inline int in(){
int x=,f=;char ch=getchar();
while(ch<''||ch>'') f=ch=='-'?-:,ch=getchar();
while(ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x*f;
}
inline void tjlca(int x,int d){
deep[x]=d;vis[x]=;
for (register int i=h[x]; i; i=edge[i].next)
if (!vis[nt])tjlca(nt,d+),fa[nt]=x;
for (register int i=q[x]; i; i=edge[i].next)
if (qans[nt]) qans[nt]=getfa(qans[nt]);
else qans[nt]=x;
}//tarjan算法求LCA
inline void dfs1(int u){
vis[u]=;ans[u]-=chafen[deep[u]-tim[u]];
for (register int i=h[u]; i; i=edge[i].next) if (vis[nt]) dfs1(nt);
for (register int i=adh1[u]; i; i=edge[i].next) ++chafen[nt];
ans[u]+=chafen[deep[u]-tim[u]];
for (register int i=deh1[u]; i; i=edge[i].next) --chafen[nt];
}//dfs处理S->f的
inline void dfs2(int u){
vis[u]=;ans[u]-=chafen[deep[u]+tim[u]];
for (register int i=h[u]; i; i=edge[i].next) if (!vis[nt]) dfs2(nt);
for (register int i=adh2[u]; i; i=edge[i].next) ++chafen[nt];
ans[u]+=chafen[deep[u]+tim[u]];
for (register int i=deh2[u]; i; i=edge[i].next) --chafen[nt];
}//dfs处理f->T的
void read(){
n=in(),m=in();int u,v;
for (int i=; i<n; ++i) u=in(),v=in(),ins(h,u,v),ins(h,v,u);
for (register int i=; i<=n; ++i) tim[i]=in()-MN;//为了防止减法出现负数,所以我们要这么做。
for (register int i=; i<=m; ++i) x[i]=in(),y[i]=in(),ins(q,x[i],i),ins(q,y[i],i);
}//输入
void init(){
tjlca(,);
for (register int i=; i<=m; ++i){
int f=qans[i],u=x[i],v=y[i];
if (f==v) ins(adh2,u,deep[u]+MN),ins(deh2,v,deep[u]+MN);
else{
if (f==u) ins(adh1,v,deep[u]+MN),ins(deh1,u,deep[u]+MN);
else{
ins(adh2,u,deep[u]+MN);
ins(deh2,f,deep[u]+MN);
ins(adh1,v,(deep[f]<<)-deep[u]+MN);
ins(deh1,f,(deep[f]<<)-deep[u]+MN);
if(deep[f]==deep[u]-tim[f]-MN) --ans[f];
}
}
}
}//处理差分位置
void solve(){
dfs1();//进行第一次遍历统计答案
for (register int i=; i<=n; ++i) tim[i]+=MN<<;//这个处理很关键!
dfs2();
for (register int i=; i<n; ++i) printf("%d ",ans[i]); printf("%d",ans[n]);
}
int main(){
read();
init();
solve();
}

【NOIP2016】【LCA】【树上差分】【史诗级难度】天天爱跑步的更多相关文章

  1. [BZOJ3307]:雨天的尾巴(LCA+树上差分+权值线段树)

    题目传送门 题目描述: N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式: 第一 ...

  2. P1600 天天爱跑步[桶+LCA+树上差分]

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

  3. [luogu P3128][USACO15DEC]Max Flow [LCA][树上差分]

    题目描述 Farmer John has installed a new system of  pipes to transport milk between the  stalls in his b ...

  4. bzoj4326 树链剖分 + 线段树 // 二分 lca + 树上差分

    https://www.lydsy.com/JudgeOnline/problem.php?id=4326 题意:N个点的树上给M条树链,问去掉一条边的权值之后所有树链长度和的最大值最小是多少. 首先 ...

  5. 2018.08.22 codves2370 小机房的树(lca+树上差分)

    传送门 一道板子题. 直接树链剖分维护树上lca然后差分就行了. 代码: #include<bits/stdc++.h> #define N 50005 #define lc (p< ...

  6. 【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家

    [题目描述:] 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真 ...

  7. [JLOI2014] 松鼠的新家 (lca/树上差分)

    [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在 ...

  8. LOJ2425 NOIP2015 运输计划 【二分+LCA+树上差分】*

    LOJ2425 NOIP2015 运输计划 LINK 题意:给你一颗树,可以将任意一条边的权值变成0,然后求m条路径的长度的最小值 思路: 先二分最后的距离ans,然后我们把路程大于ans的所有路径拿 ...

  9. poj3417 Network——LCA+树上差分

    题目:http://poj.org/problem?id=3417 根据一条边被几个环覆盖来判断能不能删.有几种情况等: 用树上差分,终点 s++,LCA s-=2,统计时计算子树s值的和即可: 用S ...

  10. [BZOJ3631]:[JLOI2014]松鼠的新家(LCA+树上差分)

    题目传送门 题目描述: 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀 ...

随机推荐

  1. linux服务器操作系统,在相同环境下,哪个做lamp服务器更稳定点?哪个版本更稳定?

    随着国内WEB服务越来越多,如何才能选择一个合适的linux服务器操作系统?在国内用的最多的好像是红帽子系列也就是red hat系列,但有些版本缺乏稳定性.新手在选择操作系统的时候最好只用偶数版本,还 ...

  2. bzoj千题计划165:bzoj5127: 数据校验

    http://www.lydsy.com/JudgeOnline/upload/201712/prob12.pdf 区间的任意一个子区间都满足值域连续 等价于 区间任意一个长为2的子区间都满足值域连续 ...

  3. $(function(){})和window.onload的区别

    (1)$(function(){}):DOM节点创建 完成才执行 (2)window.onload:页面所有资源(JS/CSS)加载完成才执行

  4. 初学者如何查阅自然语言处理(NLP)领域学术资料

    1. 国际学术组织.学术会议与学术论文 自然语言处理(natural language processing,NLP)在很大程度上与计算语言学(computational linguistics,CL ...

  5. 源码解析flask的路由系统

    源码解析flask的路由系统 当我们新建一个flask项目时,pycharm通常已经为项目定义了一个基本路由 @app.route('/') def hello_world(): return 'He ...

  6. WPF 自定义ComboBox样式

    一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样式效果: 基本样式代码如下: <!--ComboBo ...

  7. python全栈开发-re模块(正则表达式)应用(字符串的处理)

    一.概述 就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,要讲他的具体用法要讲一本书!它内嵌在Python中,并通过 re 模块实现.你可以为想要匹配的相应字符串集指定规则:该 ...

  8. 如何在Java中避免equals方法的隐藏陷阱

    摘要 本文描述重载equals方法的技术,这种技术即使是具现类的子类增加了字段也能保证equal语义的正确性. 在<Effective Java>的第8项中,Josh Bloch描述了当继 ...

  9. Docker学习笔记 - Docker的镜像

    一个容器实际上是运行在宿主机上的一个进程. 只不过在启动这个进程之前进行了一些特殊处理,让这个容器进入了一个全新的虚拟环境,与宿主机的环境分开, 所以这个进程及其子进程认为自己运行在一个独立的世界里面 ...

  10. 实现一个网易云音乐的 BottomSheetDialog

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...