【Cf #292 D】Drazil and Morning Exercise(树的直径,树上差分)

有一个经典的问题存在于这个子问题里,就是求出每个点到其他点的最远距离。
这个问题和树的直径有很大的关系,因为事实上距离每个点最远的点一定是直径的两个端点。所以我们可以很容易地进行$3$遍$Dfs$就可以算出这个了,并假设它为$d$。
我们考虑把$d$最小的点设为根,把原树变成一棵有根树,一个重要的结论就是:对于树上每一个节点,它的祖先的$d$一定比它小。
如果我们枚举了$d$最小的点$x$,那可以选择的点都是在$x$这棵子树内的,并且满足$d_{i} - d_{x} <= L$的$i$。
显然直接求解不太行,我们考虑每个点对它祖先的贡献比较合理,对于每个点$x$而言,只有距离它超过$L$的点才不会将$x$的贡献计入,我们可以倍增找到最浅的满足条件的祖先,然后在那里打上差分标记,当递归走出该点时就取消$x$的贡献。
这样我们每个询问就可以$O(nlogn)$做了。
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; typedef long long LL;
const int N = , LOG = ; int n, m, rt, ans;
int gr[LOG][N], cnt[N];
LL d[N], L; int yun, las[N], to[N << ], pre[N << ], wi[N << ];
inline void Add(int a, int b, int c) {
to[++yun] = b; wi[yun] = c; pre[yun] = las[a]; las[a] = yun;
} void Dfs(int x, int fat, LL dis) {
d[x] = max(d[x], dis);
for (int i = las[x]; i; i = pre[i]) {
if (to[i] == fat) continue;
Dfs(to[i], x, dis + wi[i]);
}
}
void Dfs_(int x, int fat) {
for (int i = ; i < LOG; ++i) {
if (gr[i - ][x]) gr[i][x] = gr[i - ][gr[i - ][x]];
}
for (int i = las[x]; i; i = pre[i]) {
if (to[i] == fat) continue;
gr[][to[i]] = x;
Dfs_(to[i], x);
}
}
int Solve(int x, int fat) {
int num = , t = x;
for (int i = las[x]; i; i = pre[i]) {
if (to[i] == fat) continue;
num += Solve(to[i], x);
}
num -= cnt[x];
ans = max(ans, num);
for (int i = LOG - ; ~i; --i) {
if (gr[i][t] && d[x] - d[gr[i][t]] <= L) t = gr[i][t];
}
++cnt[gr[][t]];
return num;
} int main() {
scanf("%d", &n);
for (int i = , x, y, z; i < n; ++i) {
scanf("%d%d%d", &x, &y, &z);
Add(x, y, z); Add(y, x, z);
}
Dfs(, , );
rt = max_element(d + , d + + n) - d;
Dfs(rt, , );
rt = max_element(d + , d + + n) - d;
Dfs(rt, , );
rt = min_element(d + , d + + n) - d;
Dfs_(rt, ); scanf("%d", &m);
for (; m; --m) {
scanf("%lld", &L);
memset(cnt, , sizeof cnt);
ans = ;
Solve(rt, );
printf("%d\n", ans);
} return ;
}
$\bigodot$ 技巧&套路:
- 树上每个点到其他点的最远距离
- 树上差分的技巧
【Cf #292 D】Drazil and Morning Exercise(树的直径,树上差分)的更多相关文章
- bzoj4326 树链剖分 + 线段树 // 二分 lca + 树上差分
https://www.lydsy.com/JudgeOnline/problem.php?id=4326 题意:N个点的树上给M条树链,问去掉一条边的权值之后所有树链长度和的最大值最小是多少. 首先 ...
- 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...
- bzoj 3307: 雨天的尾巴【树剖lca+树上差分+线段树合并】
这居然是我第一次写线段树合并--所以我居然在合并的时候加点结果WAWAWAMLEMLEMLE--!ro的时候居然直接指到la就行-- 树上差分,每个点建一棵动态开点线段树,然后统计答案的时候合并即可 ...
- BZOJ 3631 松鼠的新家 - 树链剖分 / 树上差分
传送门 分析: 树链剖分:x->y,将x到y的路径加一,并将x端点的答案-1,最后统计答案. 树上差分:x->y,x+1,y+1,lca-1,fa[lca]-1,并将x打上标记,最后统计前 ...
- bzoj3307 雨天的尾巴题解及改题过程(线段树合并+lca+树上差分)
题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式 第一行数字N,M接下 ...
- 【BZOJ3307】雨天的尾巴 题解(树链剖分+树上差分)
题目链接 题目大意:给定一颗含有$n$个结点的树,每次选择两个结点$x$和$y$,对从$x$到$y$的路径上发放一带$z$类型的物品.问完成所有操作后每个结点发放最多的时哪种物品. 普通的树链剖分貌似 ...
- P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 (树上差分+线段树合并)
显然的树上差分问题,最后要我们求每个点数量最多的物品,考虑对每个点建议线段树,查询子树时将线段树合并可以得到答案. 用动态开点的方式建立线段树,注意离散化. 1 #include<bits/st ...
- 2018.08.22 codves2370 小机房的树(lca+树上差分)
传送门 一道板子题. 直接树链剖分维护树上lca然后差分就行了. 代码: #include<bits/stdc++.h> #define N 50005 #define lc (p< ...
- 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 703 Solved: 461[Submit][Status] ...
- Wannafly Camp 2020 Day 1E 树与路径 - 树上差分,LCA
#include <bits/stdc++.h> using namespace std; #define int long long const int N = 1000005; vec ...
随机推荐
- Java-URLEncoder.encode 什么时候才是必须的
当你希望把一段 URL 当成另一个 URL 的参数时,比如:当用户点击交易的按钮时你发现未登录就跳转到 login 页面同时带上一个参数记录在登录之前用户是希望访问的那个交易页面,这样在登录完成之后再 ...
- Aspose.words Java基于模板生成word之纯文本内容
一,创建word模板 1.新建一个word文档 2.分别给四个参数设置域 (1)将鼠标置于想要设置域的地方 (2)设置域名 (3)设置好之后如下图所示 二,项目 1,引入maven依赖 <dep ...
- second scrum meeting - 151026
摘要:这一周的工作其实进行的并没有很迅速~不过我们团队的每个人都在慢慢进行自己的工作,并且我们也完成了大致的页面设计,开发了主页面的框架,并且我们也会开始着手学习服务器的操作,还有更加完善主页面的框架 ...
- Chapter 5 软件工程中的形式化方法
从广义上讲,形式化方法是指将离散数学的方法用于解决软件工程领域的问题,主要包括建立精确的数学模型以及对模型的分析活动.狭义的讲,形式化方法是运用形式化语言,进行形式化的规格描述.模型推理和验证的方法. ...
- PAT 1054 求平均值
https://pintia.cn/problem-sets/994805260223102976/problems/994805272659214336 本题的基本要求非常简单:给定N个实数,计算它 ...
- delphi 删除字符串的回车、空格、Tab键
myStr:=StringReplace(myStr, chr(13)+chr(10), '', [rfReplaceAll]);//删除回车 myStr:=StringReplace(my ...
- Delphi中使用OLE方法操作Excel
首先创建 Excel 对象,使用ComObj: var ExcelApp: Variant; ExcelApp := CreateOleObject( ′Excel.Application′ ); 注 ...
- 钉钉开发c#帮助类 获取用户信息 DingHelper.cs
using System;using System.Collections.Generic;using System.Configuration;using System.Linq;using Sys ...
- [Cnbeta]龙芯处理器性能怎么样
龙芯处理器性能怎么样?下一代CPU同频性能可达英特尔90% 在高性能处理器领域,英特尔是天花顶一般的存在(先不算地位特殊的IBM公司),国内发展CPU处理器的公司很多,绝大多数实力跟英特尔相比都差很远 ...
- [转帖]脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手
脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手 http://www.52im.net/thread-1729-1-1.html 1.引言 网络编程中TCP协议的三次握手和 ...