当前位置: 首页 > news >正文

P1600 [NOIP 2016 提高组] 天天爱跑步 分析

题目概述

题目链接:https://www.luogu.com.cn/problem/P1600。

给你一棵树,每个节点上有一个观察时间,现在有 \(m\) 个选手,选手会以每秒一个节点的速度,从 \(s_i\)\(t_i\)

求对于每个节点的观察时间能观察到多少个选手。

分析

经典题目记录一下。

显然,从 \(s_i\)\(t_i\),可以拆成 \(s_i\rightarrow lca\) 以及 \(lca\rightarrow t_i\)

于是我们分两类进行讨论。

左半部分(\(s_i\rightarrow lca\)

那么第 \(i\) 个选手能在节点 \(u\) 被观察到当且仅当:\(dep_{s_i}-dep_{u}=w_u\)

把相同下标的放一起有:\(dep_{s_i}=w_u+dep_u\)

也就是说在这条路径上面每个点需要查询自己能不能满足 \(dep_u+w_u=dep_{s_i}\),相当于我可以放 \(dep_{s_i}\) 到这个点上作为我要求的答案,这种方法在 dsu on tree 很常见。

右半部分(\(t_i\rightarrow lca\)

在节点 \(u\) 能够被观察到当且仅当:\(dep_{s_i}+dep_u-2\times dep_{lca}=w_u\)

移项可得:\(w_u-dep_u=dep_{s_i}-2\times dep_{lca}\)

结合

用两个桶存即可,只需要遍历子树,所以说直接差分。

代码

时间复杂度 \(\mathcal{O}(n+m)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#define int long long
#define N 300005
#define PII pair<int,int>
using namespace std;
const int D = 3e5;
int fa[N][30],dep[N];
vector<int> g[N];
vector<PII> add[N],del[N];
int cnt[2][N << 1];
void dfs0(int cur,int father) {fa[cur][0] = father;dep[cur] = dep[father] + 1;for (auto i : g[cur])if (i != father) dfs0(i,cur);
}
int LCA(int x,int y) {if (x == y) return x;if (dep[x] < dep[y]) x ^= y ^= x ^= y;for (int j = 25;j >= 0;j --)if (dep[fa[x][j]] >= dep[y]) x = fa[x][j];if (x == y) return x;for (int j = 25;j >= 0;j --)if (fa[x][j] != fa[y][j]) x = fa[x][j],y = fa[y][j];return fa[x][0];
}
int n,m,w[N],ans[N];
void dfs(int cur,int fa) {int pre1 = cnt[0][w[cur] + dep[cur] + D],pre2 = cnt[1] [w[cur] - dep[cur] + D];for (auto i : add[cur]) cnt[i.first][i.second + D] ++;for (auto i : del[cur]) cnt[i.first][i.second + D] --;for (auto i : g[cur])if (i != fa) dfs(i,cur);ans[cur] = cnt[0][w[cur] + dep[cur] + D] - pre1 + cnt[1][w[cur] - dep[cur] + D] - pre2;
}
signed main(){cin >> n >> m;for (int i = 1;i < n;i ++) {int u,v;scanf("%lld%lld",&u,&v);g[u].push_back(v);g[v].push_back(u);}for (int i = 1;i <= n;i ++) scanf("%lld",&w[i]);dfs0(1,0);for (int j = 1;j <= 25;j ++)for (int i = 1;i <= n;i ++)fa[i][j] = fa[fa[i][j - 1]][j - 1];for (int i = 1;i <= m;i ++) {int st,ed;scanf("%lld%lld",&st,&ed);int t = LCA(st,ed);add[st].push_back({0,dep[st]}),del[fa[t][0]].push_back({0,dep[st]});add[ed].push_back({1,dep[st] - 2 * dep[t]}),del[t].push_back({1,dep[st] - 2 * dep[t]});}dfs(1,0);for (int i = 1;i <= n;i ++) cout << ans[i] << ' ';return 0;
}
http://www.jsqmd.com/news/20870/

相关文章:

  • 2025年10月上海装修公司推荐榜:千州装饰等五家深度对比
  • 2025年10月淡化痘印产品推荐对比:从色素代谢到修护通路全解析
  • 2025年10月上海装修公司对比榜:千州装饰等五强口碑解析
  • 2025年10月敏感肌美白面霜推荐榜:淡斑修护综合排名
  • SQL - 递归查询子节点
  • 2025年10月色斑淡化产品对比榜:五款精华通路机制深度解析
  • 2025年10月医美项目后用什么产品评测榜:术后舒缓精华口碑对比
  • 一些c语言特殊用法
  • 题解:P4204 [NOI2006] 神奇口袋
  • 2025年超声波检测设备厂家权威推荐榜:相控阵/高频/水浸/液冷板/钎焊超声波检测系统,技术实力与选购指南深度解析
  • 2025年环氧板厂家推荐排行榜,环氧板加工,FR-4玻纤板,云母板,专业定制与优质材料供应商精选
  • sql server查看所有表名以及注释
  • SQL - 递归查询父节点
  • 2025.10.24——1绿
  • 2025年精密弹簧厂家权威推荐榜单:压缩弹簧、拉伸弹簧、扭转弹簧、异形弹簧专业制造商综合评测与选购指南
  • PyQuokka框架存在Pickle反序列化远程代码执行漏洞
  • 2025年磨粉机厂家推荐排行榜,雷蒙磨粉机,环辊磨粉机,摆式磨粉机,矿石磨粉机,超细磨粉机,高压磨粉机,大型磨粉机公司推荐
  • SQL Server 建表语句
  • 2025年润滑油厂家权威推荐榜:工业润滑油,汽车润滑油,发动机润滑油,甲醇发动机润滑油,三特/三球/安迪森润滑油,全合成润滑油,中国润滑油,长效发动机润滑油厂家精选
  • SQL Server 报错引用了无效的表`表名`
  • 2025年氢氧化镁厂家权威推荐榜:矿石氢氧化镁/水镁石氢氧化镁/阻燃剂氢氧化镁/改性氢氧化镁源头企业综合评测与采购指南
  • Nexpose 8.25.0 for Linux Windows - 漏洞扫描
  • NVIDIA —— 智能仓储
  • 工作出行计划 —— 15号出发去石家庄,参加17号的会展 —— 2025中国国际数字经济博览会10月17日至19日在石家庄举行
  • 人工智能学院课程设计
  • 2025年冲压件厂家推荐排行榜,新能源冲压件,光伏冲压件,精密冲压件,异形冲压件,五金冲压件,铝冲压件,汽配冲压件,不锈钢冲压件,家具冲压件公司推荐
  • 2025年电源适配器厂家权威推荐榜单:开关电源适配器,笔记本电源适配器,手机电源适配器,工业电源适配器公司精选
  • 2025年环保空调厂家权威推荐榜:移动式环保空调,节能环保空调,工业环保空调源头厂家综合解析与选购指南
  • 2025年氧化镁厂家最新推荐排行榜,活性氧化镁,肥料级氧化镁,高纯度氧化镁,工业级氧化镁优质供应商精选
  • 2025年10月肤色暗沉产品评测榜:五款温和亮肤方案指南