天天爱跑酷

  传送门:天天爱跑步 NOIP 2016 T4

题目大意

  给你一棵树,有 mmm 个玩家,每个玩家在 000 时刻从 sis_isi​ 跑到 tit_iti​,速度都是每秒一条边。每个节点上有一个观察员,并且第 iii 个节点上的观察员会在第 wjw_jwj​ 秒观察这个节点。现在要求每个节点的观察员会观察到多少个玩家。

  一个玩家被观察到当且仅当他在 wiw_iwi​ 秒时经过节点 iii。

算法分析

  我们考虑将一个玩家 s→ts \to ts→t 的路径拆开,变成 s→lca(s,t)→ts \to lca(s, t) \to ts→lca(s,t)→t。分别考虑这两段路径上会不会被观察到。

  1. 首先时 s→lca(s,t)s \to lca(s, t)s→lca(s,t) 这一段。我们可以很容易想到,如果要在这一段被观察到,就必须满足这样一个式子: deps−depi=widep_s - dep_i = w_ideps​−depi​=wi​,其中 depidep_idepi​ 表示节点 iii 在这棵树中的深度。我们稍微移一下项: deps=depi+widep_s = dep_i + w_ideps​=depi​+wi​。我们会发现右边这一坨对于每一个节点是一个定值,所以我们的任务就变成了,对于每一个节点 iii 找有多少个 sss 满足这个式子。
  2. 然后 lca(s,t)→tlca(s, t) \to tlca(s,t)→t 这一段也是同理。我们令 dis(x,y)=depx+depy−2deplca(x,y)dis(x, y) = dep_x + dep_y - 2dep_{lca(x, y)}dis(x,y)=depx​+depy​−2deplca(x,y)​,那么这一段里面就是满足: depi+dis(s,t)−dept=widep_i + dis(s, t) - dep_t = w_idepi​+dis(s,t)−dept​=wi​,移一下项:dept−dis(s,t)=depi−widep_t - dis(s, t) = dep_i - w_idept​−dis(s,t)=depi​−wi​。这需要注意因为不保证 depi>widep_i > w_idepi​>wi​,所以我们实际操作的时候应该把等式左右两边都加上 nnn 来统计。

  我们以的 s→lca(s,t)s \to lca(s, t)s→lca(s,t) 为例,我们要找的就是在 iii 的子树中,有多少节点满足 deps=wi+depidep_s = w_i + dep_ideps​=wi​+depi​。那么问题就能转化成对于一个 sss,我们在从 s→lcas \to lcas→lca 的路径上的所有点上全都放上一个类型为 depsdep_sdeps​ 的物品,然后对于点 iii 我们要查找类型为 depi+widep_i + w_idepi​+wi​ 的物品的个数。这样我们很容易就能想到树上差分。

  具体来说就是每个节点上放一个桶,然后对于每一个路径在桶里面操作差分就好了。最后统计就直接算子树和。但是这样的空间复杂度都有点爆炸,是 O(n2)O(n^2)O(n2) 的。所以我们考虑优化这个做法。

  既然不能每个点都开一个桶,我们就考虑全局开桶,具体来说,我们对树上的每一个节点开一个 vectorvectorvector,存储差分的时候我们进行的修改。然后我们全局开一个桶(其实是两个,因为有两种路径)。然后我们做一遍 dfsdfsdfs。

  在 dfsdfsdfs 到点 xxx 的时候我们记录 cntcntcnt 表示当前还没有继续进入子树的时候 depx+wxdep_x + w_xdepx​+wx​ 类型物品的个数,然后我们再处理这个点对于桶的贡献(就是书上差分求和),最后再继续向下 dfsdfsdfs。再一次从子树回到这个点的时候,我们就能统计这个点的答案就是现在的 depx+wxdep_x + w_xdepx​+wx​ 的个数减去前面我们记录的没有进入子树时的个数。

  完结撒花!!!

代码

#include<bits/stdc++.h>
using namespace std;
#define in read()
#define MAXN 300300
#define MAXM MAXN << 2inline int read(){int x = 0; char c = getchar();while(c < '0' or c > '9') c = getchar();while('0' <= c and c <= '9'){x = x * 10 + c - '0'; c = getchar();}return x;
}int w[MAXN] = { 0 };
int n = 0; int m = 0;
struct Tnode{int opt, val, c;                     // 路径种类, 值, 差分 Tnode(int o = 0, int v = 0, int C = 0) { opt = o, val = v, c = C; }
};
vector<Tnode> num[MAXN];
int tot = 0;
int first[MAXN] = { 0 };
int   nxt[MAXM] = { 0 };
int    to[MAXM] = { 0 };
int   dep[MAXN] = { 0 };
inline void add(int x, int y){nxt[++tot] = first[x];first[x] = tot; to[tot] = y;
}int f[MAXN][50];
void prework(int x, int fa){dep[x] = dep[fa] + 1;for(int i = 0; i <= 30; i++) f[x][i + 1] = f[f[x][i]][i];for(int e = first[x]; e; e = nxt[e]){int y = to[e];if(y == fa) continue;f[y][0] = x; prework(y, x);}
}int Lca(int x, int y){if(dep[x] < dep[y]) swap(x, y);for(int i = 30; i >= 0; i--){if(dep[f[x][i]] >= dep[y]) x = f[x][i];if(x == y) return x;}for(int i = 30; i >= 0; i--)if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];return f[x][0];
}int up[MAXN] = { 0 };                                 // s -> lca(s, t) 的路径
int down[MAXN] = { 0 };                               // lca(s, t) -> t
int ans[MAXN] = { 0 };
void dfs(int x, int fa){int cnt = up[dep[x] + w[x]] + down[dep[x] - w[x] + n];for(int i = 0; i < num[x].size(); i++){                 // 差分子树和 Tnode t = num[x][i];if(t.opt == 1) up[t.val] += t.c;if(t.opt == 2) down[t.val] += t.c;}for(int e = first[x]; e; e = nxt[e]){int y = to[e];if(y == fa) continue;dfs(y, x);}ans[x] = up[dep[x] + w[x]] + down[dep[x] - w[x] + n] - cnt;
}int main(){n = in; m = in;for(int i = 1; i < n; i++){int x = in, y = in;add(x, y), add(y, x);} prework(1, 0);for(int i = 1; i <= n; i++) w[i] = in;for(int i = 1; i <= m; i++){int s = in, t = in;int lca = Lca(s, t), dis = dep[s] + dep[t] - 2 * dep[lca];num[s].push_back(Tnode(1, dep[s], 1));num[lca].push_back(Tnode(1, dep[s], -1));num[t].push_back(Tnode(2, dep[t] - dis + n, 1));num[f[lca][0]].push_back(Tnode(2, dep[t] - dis + n, -1));} dfs(1, 0);for(int i = 1; i <= n; i++) cout << ans[i] << ' '; puts("");return 0;
}

天天爱跑步【NOIP2016 T4】相关推荐

  1. luoguP1600 天天爱跑步(NOIP2016)(主席树+树链剖分)

    阅读体验: https://zybuluo.com/Junlier/note/1303550 为什么这一篇的Markdown炸了? # 天天爱跑步题解(Noip2016)(桶+树上差分 ^ 树剖+主席 ...

  2. 天天爱跑步noip2016

    洛谷 跟隔壁的雨天的尾巴异常相似 ----------------------------------------------------------------------------------- ...

  3. [UOJ] #261 天天爱跑步

    #261. 天天爱跑步 NOIP2016 D1T2 题目描述 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按 ...

  4. NOIP2016天天爱跑步

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

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

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

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

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

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

    题目背景 NOIP2016 提高组 Day1 T2 题目描述 小 C 同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每 ...

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

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

  9. $NOIP2016$天天爱跑步

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

最新文章

  1. HTTPS通信的C++实现
  2. matlab考试湖北理工学院,电子信息工程导论课程教学大纲-电气与电子信息工程学院-湖北.DOC...
  3. 卷积神经网络——池化层学习——最大池化
  4. swing下拉框从mysql_Java Swing应用程序 JComboBox下拉框联动查询
  5. chrome同步_如何在Chrome中打开或关闭同步
  6. python画统计图代码_Python使用统计函数绘制简单图形实例代码
  7. centos8安装中文(zh_CN)语言包
  8. MongoDB出错:ERROR: child process failed, exited with error number 1 To see additional infor
  9. fedora yum 安装mysql
  10. HDU3544 不平等博弈
  11. python import包导出变量_Python关于import的实验(10) 利用__init__.py文件将变量和包下的模块作为包的属性...
  12. win10专业版没有触摸板选项_win10没有显示触摸板
  13. 物联网安全专题 | 浅谈物联网设备安全分析方法 — 硬件篇
  14. c语言string函数的用法_C语言让电脑关机?system函数功能够大够硬
  15. is_enabled:selenium中判断元素是否可以使用;is_selected()/is_displayed()
  16. 谷歌2018年IO大会
  17. 十条网站盈利模式分析总结
  18. Cocos Creator AnySDK支付问题
  19. 使用Web浏览器访问远程ssh终端
  20. ❤️❤️❤️Unity废柴看过来,手把手教你做植物大战僵尸(十二)—— 向日葵生产太阳

热门文章

  1. 京东区块链开源项目——JD Chain介绍及区块链白皮书发布
  2. win10系统如何关闭服务器,win10命令关闭服务器该怎么操作关闭?
  3. Echarts地图标记重合问题原因
  4. ubuntu下u盘变成只读模式
  5. 2021年塔式起重机司机模拟考试题及塔式起重机司机作业考试题库
  6. Java核心技术卷一基础知识第10版demo实例
  7. 公纵号发送提示信息(用户微服务--消息微服务)
  8. matlab电影,如何制作电影(与matlab相关)?
  9. 数据结构与算法基础学习(一)
  10. 以大数据、云计算、人工智能、区块链为代表的新技术,开始充当底层技术