一道综合性非常强的好题
最朴素的做法,便是模拟:模拟某一个玩家的移动(假设是从u跑到v,那么求出u与v的LCA w,然后考察u->w与v->w上的点即可),在到达某个节点时判断能否被这个点上的观察员观察到。
这样做肯定是会t的,不过会为我们提供一个思路:
假设出发时间是st_u,并且j是从u->v路径上的一个节点,那么如果有st_u+dis(u,j)==W[j],这个u->的玩家便会对j产生贡献
dis(u,j)怎么计算呢?用LCA,u,j的dep进行计算就可以了。
为了方便讨论,我们把路径分为向上的路径和向下的路径;对于u->lca->v的路径,只需要拆成u->w和w->v即可。
开始大力推式子:

(本人十分懒惰,于是直接把草稿纸给照了上来)
所以我们可以用开桶的方式来对每个玩家产生贡献的“特征值“进行统计
在计算某个观察员观察到的玩家数量时,根据桶里面相应特征值的数目即可得到答案
不过还有几个比较麻烦的细节:
考虑u->w->v的情况,如果这个玩家能被w处观察员看到,那么会被w处观察员统计两次
所以我们要在处理lca的时候就预判这种情况,先给Ans[w]–
另外,如何保证我们统计到的玩家数量一定会经过这个点呢?
这个比较麻烦,得分情况讨论(我还是认真点作个图好了)

以上,代码如下

#include<bits/stdc++.h>
using namespace std;const int MAXN=3e5+5;
const int D=6e5;int N,M;
int Dep[MAXN],lg2[MAXN],W[MAXN],Ans[MAXN];
int Fa[MAXN][20];
int Bac_Up[MAXN<<3],Bac_Down[MAXN<<3];
vector<int>G[MAXN];
vector<int>Up_st[MAXN],Up_ed[MAXN],Down_st[MAXN],Down_ed[MAXN];void Prepare(int cur,int pre) {Dep[cur]=Dep[pre]+1;Fa[cur][0]=pre;for(int k=1; k<=lg2[Dep[cur]]; k++)Fa[cur][k]=Fa[Fa[cur][k-1]][k-1];for(int i=0; i<G[cur].size(); i++) {int ver=G[cur][i];if(ver==pre)continue;Prepare(ver,cur);}
}int LCA(int u,int v) {if(Dep[u]<Dep[v])swap(u,v);while(Dep[u]>Dep[v])u=Fa[u][lg2[Dep[u]-Dep[v]]];if(u==v)return u;for(int k=lg2[Dep[u]]; k>=0; k--)if(Fa[u][k]!=Fa[v][k])u=Fa[u][k],v=Fa[v][k];return Fa[u][0];
}void Dfs_Up(int cur,int pre) {int tmp=Bac_Up[W[cur]+Dep[cur]];for(int i=0; i<G[cur].size(); i++) {int ver=G[cur][i];if(ver==pre)continue;Dfs_Up(ver,cur);}for(int i=0; i<Up_st[cur].size(); i++)Bac_Up[Up_st[cur][i]]++;Ans[cur]+=Bac_Up[W[cur]+Dep[cur]]-tmp;for(int i=0; i<Up_ed[cur].size(); i++)Bac_Up[Up_ed[cur][i]]--;
}void Dfs_Down(int cur,int pre) {for(int i=0; i<Down_st[cur].size(); i++)Bac_Down[Down_st[cur][i]+D]++;//start from this pos to go down the treeint tmp=Bac_Down[W[cur]-Dep[cur]+D];for(int i=0; i<Down_ed[cur].size(); i++)Bac_Down[Down_ed[cur][i]+D]--;for(int i=0; i<G[cur].size(); i++) {int ver=G[cur][i];if(ver==pre)continue;Dfs_Down(ver,cur);}//minus the roads end in the subtree to calclulate the answerAns[cur]+=tmp-Bac_Down[W[cur]-Dep[cur]+D];
}int main() {//freopen("in.txt","r",stdin);//freopen("ou.txt","w",stdout);ios::sync_with_stdio(false);cin>>N>>M;for(int i=2; i<=N; i++)lg2[i]=lg2[i>>1]+1;for(int i=1,u,v; i<N; i++) {cin>>u>>v;G[u].push_back(v);G[v].push_back(u);}Prepare(1,0);for(int i=1; i<=N; i++)cin>>W[i];//for(int i=1;i<=N;i++)//   cout<<W[i]<<" ";//cout<<endl;for(int i=1,s,t; i<=M; i++) {cin>>s>>t;//++Ans[s];int w=LCA(s,t);if(w!=s&&w!=t) {Up_st[s].push_back(Dep[s]);Up_ed[w].push_back(Dep[s]);Down_st[w].push_back(Dep[s]-2*Dep[w]);Down_ed[t].push_back(Dep[s]-2*Dep[w]);if(W[w]==Dep[s]-Dep[w])--Ans[w];} else if(s==w) {Down_st[s].push_back(-Dep[s]);Down_ed[t].push_back(-Dep[s]);} else {Up_st[s].push_back(Dep[s]);Up_ed[t].push_back(Dep[s]);}}Dfs_Up(1,0);Dfs_Down(1,0);for(int i=1; i<=N; i++)cout<<Ans[i]<<' ';return 0;
}

NOIP2016 天天爱跑步相关推荐

  1. NOIP2016天天爱跑步

    NOIP2016天天爱跑步 这题一看显然lca+树上差分,但是因为有w的限制不能直接加,所以考虑权值线段树合并, 每个选手的起点终点对于不同的节点的影响是不同的,这就非常麻烦了,但是可以发现无论如何他 ...

  2. [NOIp2016]天天爱跑步 线段树合并

    [NOIp2016]天天爱跑步 LG传送门 作为一道被毒瘤出题人们玩坏了的NOIp经典题,我们先不看毒瘤的"动态爱跑步"和"天天爱仙人掌",回归一下本来的味道. ...

  3. [NOIP2016]天天爱跑步(lca+乱搞)

    2557. [NOIP2016]天天爱跑步 时间限制:2 s   内存限制:512 MB [题目描述] 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑 ...

  4. $NOIP2016$天天爱跑步

    \(NOIP2016\)天天爱跑步 真\(™\)是\(NOIP\)近几年中最难的一道-- 先看一下部分分,有起点终点为根节点的分值,想到拆路径,对于路径\((S,T)\),拆为\((S,LCA)\)和 ...

  5. NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】

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

  6. [NOIP2016]天天爱跑步 题解(树上差分) (码长短跑的快)

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

  7. [noip2016]天天爱跑步

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

  8. 【题解】NOIP-2016 天天爱跑步

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

  9. [noip2016]天天爱跑步(主席树+lca)

    恩..在百度的第一页翻了翻,没有用主席树做的,于是打算水一篇blog: 天天爱跑步 首先有一个解题的关键: 将玩家的向上和向下分成两部分: 先定义几个变量,s是起点,t是终点,wi是每个观察员出现的时 ...

  10. NOIP2016 天天爱跑步(线段树/桶)

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

最新文章

  1. 如何将全景分割用到养猪场?
  2. XamarinEssentials教程移除键值首选项的键值
  3. nodejs连接池 连接关闭_「转」连接池居然这么简单?
  4. java中生成pdf文件,java 中生成pdf 文件
  5. 光伏电池最大功率跟踪
  6. Linux系统,Hadoop,R语言,RHadoop的安装
  7. 推荐一个宝藏公众号,附大数据PPT合集下载
  8. 神经网络学习小记录64——Pytorch 图像处理中注意力机制的解析与代码详解
  9. 从降维攻击详解互联网格局体系
  10. 设计模式08—模板方法模式
  11. 物理机无法ping通虚拟机,虚拟机能ping通物理机
  12. 弘辽科技:店铺前期可以不上宝贝吗?店铺如何上宝贝?
  13. 服务器虚拟机控制台打不开,OpenStack虚拟机控制台打不开
  14. Layer Tree 绘制
  15. 自适应均衡器的设计与仿真
  16. 抽屉原理解释及简单举例
  17. Spark 内存管理存储内存管理_尚硅谷大数据培训
  18. Element ui —— dialog 弹窗 设置点击空白处不关闭
  19. linux程序启动后查不到进程,Linux应用程序 启动流程
  20. 同步任务和异步任务执行过程

热门文章

  1. Mavenir被以色列Partner选为下一代网络
  2. NFS 服务 lap1+lap2+mysql+nfs
  3. Android设备实时音视频传输有效方案
  4. python统计中文字符数量
  5. Hypergraph Neural Networks HGNN
  6. www.050604.pw ub.php,BOL_050604_M_010
  7. Prim算法解决最小生成树 (解决修路问题)
  8. 宋丹丹晒年轻旧照 桃眼杏腮被赞美女
  9. linux文件目录基本操作实验结论,实验 Linux文件和目录操作
  10. Excel数据的导入