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

P4178 Tree (点分治)

题目链接

一:我们考虑树上两点之间的路径有什么情况
1:经过根节点(即在根节点的两端)
2:不经过根节点(完全在一颗子树的一侧)

二:我们考虑这两种路径是否可以归为一类
1:对于第一种的情况两点间路径长度dis( u , v ) 可以看为dis ( u , root ) + dis ( root , v ) 
2:而对于第二种情况我们可以找到u , v 路径所在的子树,将根节点变为子树的根节点,然后就变为了第一种情况
3:总之,所以我们可以不断的递归根节点将所有情况转化为第一种情况
设b[ u ] 表示u属于哪一棵子树(b数组在算法进阶指南里说了,但是代码好像没有体现,而是用了容斥原理)
那么b[ u ] = b[ v ] ,d[ u ] + d[ v ] ≤ k满足条件的第一类路径条数即为满足条件的点对数


三:下面我们来讨论如何计算满足条件的点对数:
1:将目前子树中的节点到根节点的权值放入数组len中,并排序
用两个指针 L,R 扫描数组,每找到一个合法的答案就加上R −L ,就让L++,否则让 R --
2:发现问题

在指针扫描的过程中我们会出现不合的情况

根据len的定义我们存放的一颗树里面所有的边,这是我们计算calc计算时,可能会加上两条边在子树的同一侧的情况,我们可以发现不合法的路径在当前根的一颗子树上,即没有跨越两棵子树(如果跨越了它就合法了),所以们可以在遍历的时候减去不合法的情况(容斥)

3:具体的方法
ans+ = calc( u , 0 ) 
ans − =calc ( v , dis ( u , v ) ) 

这样即可做到不重不漏

四:总结

点分治步骤
  • 找到树的重心
  • 将重心视为根节点,那么树上任意两点有两种情况
  • 路径经过根节点
  • 路径不经过根节点
  • 通过 calc  函数计算出第一种情况下的答案,把根节点从树中删去
  • 对每棵子树递归执行上面的操作

calc函数的计算方法

  • 计算出每个结点到根节点的距离 d [ i ]
  • 将树上的结点按照 d [ i ] 递增排序
  • 指针 l  指向 d [ 1 ] ,指针 r 指向 d [ n ]。
  • 若 l 与 r 指向结点的距离小于 k  ,则 ans + = r − l + 1 , l + + 。
  • 否则 r − −。
  • 当 l > = r  的时候退出循环。
  • 按照上面的方法,会把不经过根节点的路径也算入进去。利用容斥原理修正答案:

五:更具体的做法,见注释

#include <bits/stdc++.h>
using namespace std;
#define pi acos(-1)
#define xx first
#define yy second
#define endl "\n"
#define lowbit(x) x & (-x)
#define int long long
#define ull unsigned long long
#define pb push_back
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define Ysanqian ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
const int N = 1e6 + 10, M = 1010, inf = 0x3f3f3f3f, mod = 18446, P = 13331;
const double eps = 1e-8;
int n, k, root, sum, ans;
vector<PII> g[N];
int siz[N], max_part[N], d[N], b[N], len[N];
bool st[N];
void get_root(int u, int fa) // 找出重心
{siz[u] = 1, max_part[u] = 0; // siz[i]为其子树的大小,max_part[i]为去掉i后的最大连通块大小for (auto ed : g[u]){int v = ed.xx;if (v == fa || st[v])continue;get_root(v, u);siz[u] += siz[v];max_part[u] = max(max_part[u], siz[v]);}max_part[u] = max(max_part[u], sum - siz[u]);if (max_part[u] < max_part[root]) // 一开始root为0,且将其赋值为 n即为maxroot = u;
}
void get_dis(int u, int fa) // 找出这颗子树的距离。
{len[++len[0]] = d[u]; // len[0]存放的是子树节点个数,len[i] 表示子树中的路径长度for (auto ed : g[u]){int v = ed.xx, w = ed.yy;if (v == fa || st[v])continue;d[v] = d[u] + w; // d[i] 表示i到根节点的距离,由上而下的去跟新d数组,因为子节点距离有父节点跟新而来,故在计算距离时只更新父节点即可get_dis(v, u);}
}
int calc(int u, int w) // 计算以u为根的第一种情况的答案,也就是在树的两边的,但是对于只在一边得还未计算
{d[u] = w, len[0] = 0;            // 先给根节点一个值,如果为0说明在递归子树,不是0那就是再利用容斥出去冗余,将该子树的边数先归零get_dis(u, 0);                   // 计算改子树的距离根节点的距离sort(len + 1, len + len[0] + 1); // 将距离从小到大排序int res = 0;for (int l = 1, r = len[0]; l < r;) // 直到不论左移还是右移都大于k,if和else if 都进不去{if (len[l] + len[r] <= k) // l与最大的相加都小于k,其余也小于k{res += r - l; // 故加上r-l++l;          // 右移左端点}elser--; // 否则左移右端点}return res; // 返回以u为根的所有情况的答案
}
void solve(int u)
{st[u] = 1;           // 标记删除的重心,防止重复计算ans += calc(u, 0);   // 加上以我为跟答案for (auto ed : g[u]) // 遍历子树{int v = ed.xx, w = ed.yy;if (st[v])continue;ans -= calc(v, w); // 减去不合法得情况,不合法的情况全都发生在一课子树上,这里为什么传w,因为我们要加上u与v的边权sum = siz[v];      // 不要忘记在以v为根节点时,要修改all_node 的大小root = 0;get_root(v, u); // 递归根节点,但是肯定会有重复solve(root);    // 递归解决}
}
signed main()
{Ysanqian;cin >> n;sum = n;max_part[0] = n; // 让max_part[0]为n当一个哨兵,以便跟新max_part[i]for (int i = 1; i < n; i++){int a, b, c;cin >> a >> b >> c;g[a].pb({b, c}); // 建边g[b].pb({a, c});}cin >> k;get_root(1, -1); // 先找重心solve(root);     //cout << ans << endl;return 0;
}

相关文章:

P4178 Tree (点分治)

题目链接 一&#xff1a;我们考虑树上两点之间的路径有什么情况 1&#xff1a;经过根节点&#xff08;即在根节点的两端&#xff09; 2&#xff1a;不经过根节点&#xff08;完全在一颗子树的一侧&#xff09; 二&#xff1a;我们考虑这两种路径是否可以归为一类 1&#xff1…...

Kubernetes 二进制搭建

Kubernetes 二进制搭建 一、二进制搭建 Kubernetes v1.201.1 部署准备1.2 操作系统初始化配置1.3 部署 etcd 集群1.3.1 etcd 作为服务发现系统&#xff0c;有以下的特点1.3.2 准备签发证书环境1.3.3 在 master01 节点上操作1.3.4 生成证书 1.4 部署 docker引擎1.4.1 部署 Maste…...

QT QtXlsx安装使用

QtXlsx介绍 QtXlsx是一个可以读取和写入Excel文件的库。它不需要Microsoft Excel&#xff0c;可以在Qt5支持的任何平台上使用。 这里一定是需要QT5支持的。 须知安装QtXlsx时&#xff0c;需要下载perl 1.安装perl 这里选择官网下载安装即可。 官网地址&#xff1a;https://p…...

Java医院信息化HIS管理系统源码

HIS模板分为两种&#xff1a;病历模板和报表模板。模板管理是运营管理的核心组成部分&#xff0c;是基层卫生健康云中各医疗机构定制电子病历和报表的地方&#xff0c;各医疗机构可根据自身特点特色定制电子病历和报表&#xff0c;制作的电子病历及报表可直接在业务系统中使用。…...

【Uni-App】uview 开发多端应用,密码显示隐藏功能不生效问题

出现的问题&#xff1a; 使用uview组件u-input框密码绑定时会出现右侧密码显隐图标不显示的问题 思路&#xff1a; 1.看了下uview源码&#xff0c;发现这有一段注释&#xff0c;我们需要把源码修改一下&#xff0c;问题出在这里 这行代码修改为 :password"password || …...

人工智能算法-SVM, KNN

目录 SVM, KNN区别 一、KNN算法概述 算法的描述: 二、关于K的取值 K的取法: 三、关于距离的选取 Euclidean Distance 定义: 四、总结 SVM, KNN区别...

计算机网络—TCP

这里写目录标题 TCP头格式有哪些为什么需要TCP&#xff0c;TCP工作在哪什么是TCP什么是TCP连接如何确定一个TCP连接TCP和UDP的区别&#xff0c;以及场景TCP和UDP能共用一个端口&#xff1f;TCP的建立TCP三次握手过程为什么是三次握手、不是两次、四次why每次建立连接&#xff0…...

Oracle到DM实时数据同步实施方案

目录 1 项目概述 2 需求分析 3 实施操作 3.1 历史数据全量同步 3.2 增量数据实时同步 4 问题总结 4.1 字符型非空约束 4.2 字符型唯一索引尾部空格 1 项目概述 将Oracle 11g RAC生产环境数据同步到DM8分析环境&#xff0c;Oracle数据库大小1.5T&#xff0c;日增归档10…...

WebRTC | 音视频实时通信的本质

目录 一、音视频实时通信的两种指标 1. 实时通信延迟指标 2. 视频相关的基本概念 3. 音视频服务质量指标 二、解决实时通信的主要矛盾 1. 增加带宽 A. 提供更优质的接入服务 B. 保证云端网络的带宽和质量 C. 更合理的路由调度策略 2. 减少数据量 A. 采用更好的压缩算…...

ApiPost的使用

1. 设计接口 请求参数的介绍 Query:相当于get请求&#xff0c;写的参数在地址栏中可以看到 Body: 相当于 post请求&#xff0c;请求参数不在地址栏中显示。 请求表单类型&#xff0c;用form-data json文件类型&#xff0c;用row 2. 预期响应期望 设置完每一项点一下生成响应…...

6、CCS 配置工程头文件批量添加路径的方法

1、进入到图示的框框里 2、编辑好需要添加的路径&#xff0c;并按ctrl c 3、选中include paths&#xff08;-I&#xff09;框框里的最后一条路径 4、然后ctrl v&#xff0c;这样路径就复制到预定义路径里了...

Visual Studio配置PCL库

Visual Studio配置PCL库 Debug和Release配置新建项目配置属性表测试参考 Debug和Release Debug和Release的配置过程一模一样&#xff0c;唯一区别就在于最后一步插入的附加依赖项不同&#xff0c;因此下面以debug为例。 配置新建项目 1、新建一个C空项目&#xff0c;模式设置…...

数据分析 | 为什么Bagging算法的效果优于单个评估器

1. 回归问题如何降低方差 以随机森林为例&#xff0c;假设随机森林中含有n个弱评估器&#xff0c;由于子样本集的相似性以及使用的是同种模型&#xff0c;因此各模型有近似相等的方差和偏差&#xff0c;因此假设任意弱评估器上输出结果为,方差均为&#xff0c;则随机森林的输出…...

mysql架构介绍

1.整体架构图 我们发现整体的体系是由连接层、服务层、引擎层和物理文件存储层组成。 1.连接层 连接层是处理客户端和服务端之间的通信的&#xff0c;比如一些连接处理、授权验证等等。 2.服务层 服务层主要完成核心的功能&#xff0c;如SQL接口&#xff0c;就是用来接收…...

EIK+Filebeat+Kafka

目录 一、Kafka 概述 1&#xff09;为什么需要消息队列&#xff08;MQ&#xff09; 2&#xff09;使用消息队列的好处 &#xff08;1&#xff09;解耦 &#xff08;2&#xff09;可恢复性 &#xff08;3&#xff09;缓冲 &#xff08;4&#xff09;灵活性 & 峰值处理…...

python安装xgboost报错

ERROR: Could not find a version that satisfies the requirement xgboost (from versions: none) ERROR: No matching distribution found for xgboost 解决办法&#xff1a; 换成国内的pip源 pip install xgboost -i http://pypi.doubanio.com/simple/ --trusted-host py …...

语音芯片的型号有哪些?为什么强烈推荐使用flash型可擦写的

一、语音芯片的简介 语音芯片的型号有哪些&#xff1f;为什么强烈推荐使用flash型可擦写的芯片。这里我们简单描述一下如下常见类容&#xff1a; 1、他们都有什么特点&#xff1f;以及发展的历程简介 2、常见的语音芯片有哪些&#xff1f; 3、为什么推荐使用flash型可以重复…...

【OpenCV常用函数:轮廓检测+外接矩形检测】cv2.findContours()+cv2.boundingRect()

文章目录 1、cv2.findContours()2、cv2.boundingRect() 1、cv2.findContours() 对具有黑色背景的二值图像寻找白色区域的轮廓&#xff0c;因此一般都会先经过cvtColor()灰度化和threshold()二值化后的图像作为输入。 cv2.findContous(image, mode, method[, contours[, hiera…...

opencv,opengl,osg,vulkan,webgL,opencL,cuda

OpenCV OpenCV是一个基于BSD许可&#xff08;开源&#xff09;发行的跨平台计算机视觉和机器学习软件库&#xff0c;可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效——由一系列 C 函数和少量 C 类构成&#xff0c;同时提供了Python、Ruby、MATLAB等…...

golang拥有wireshark数据包解析能力

golang拥有wireshark数据包解析能力 1. 功能和实现 wireshark拥有世界上最全面的协议解析能力并且还在不断更新中&#xff0c;通过调研&#xff0c;没有办法找到与wireshark同水平的解析工具。 为了使得golang语言可以拥有wireshark一样强大的协议解析能力&#xff0c;库 gowir…...

thinkphp-queue队列随笔

安装 # 创建项目 composer create-project topthink/think 5.0.*# 安装队列扩展 composer require topthink/think-queue 配置 // application/extra/queue.php<?php return [connector > Redis, // Redis 驱动expire > 0, // 任务的过期时间…...

STM32实战:数字音频播放器开发指南

基于STM32的数字音频播放器/效果器是个很棒的项目&#xff01;这涉及到多个嵌入式开发的关键技术点。下面我为你拆解实现方案和关键学习内容&#xff1a; 系统架构概览 [SD Card] -> [File System (FATFS)] -> [Audio Decoder (WAV/MP3)] -> [DSP Processing (EQ, R…...

使用API网关Kong配置反向代理和负载均衡

简介 Kong 是一个微服务API网关。 Kong是一个云原生&#xff0c;快速&#xff0c;可扩展和分布式微服务抽象层&#xff08;也称为API网关&#xff0c;API中间件或在某些情况下为Service Mesh&#xff09;。 作为2015年的开源项目&#xff0c;其核心价值在于高性能和可扩展性。…...

2025服装收银系统推荐:智能管理助力服装商家高效经营

在服装批发零售行业&#xff0c;一套高效的收银系统不仅能简化日常经营流程&#xff0c;还能通过数据分析帮助商家优化库存、提升销售。随着AI技术的普及&#xff0c;现代收银系统已不再局限于简单的记账功能&#xff0c;而是能提供智能选品、库存预警、精准营销等进阶服务。 …...

解决 VSCode 中无法识别 Node.js 的问题

当 VSCode 无法识别 Node.js 时&#xff0c;通常会出现以下症状&#xff1a; 代码提示缺失require 等 Node.js API 被标记为错误调试功能无法正常工作终端无法运行 Node.js 命令 常见原因及解决方案 1. Node.js 未安装或未正确配置 ​​解决方法​​&#xff1a; 确保已安…...

1panel面板中部署SpringBoot和Vue前后端分离系统 【图文教程】

1panel面板中部署SpringBoot和Vue前后端分离系统 一&#xff0c;1panel面板部署二&#xff0c;安装OpenResty三&#xff0c;安装MySQL&#xff0c;Redis等Spring boot 运行依赖环境四&#xff0c;SpringBoot 应用配置及打包部署配置打包部署 五 &#xff0c;前端VUE应用配置打包…...

JavaScript性能优化实战:从核心原理到工程实践的全流程解析

下面我给出一个较为系统和深入的解析&#xff0c;帮助你理解和实践“JavaScript 性能优化实战&#xff1a;从核心原理到工程实践的全流程解析”。下面的内容不仅解释了底层原理&#xff0c;也结合实际工程中的最佳模式和工具&#xff0c;帮助你在项目中贯彻性能优化理念&#x…...

Web前端之原生表格动态复杂合并行、Vue

MENU 效果公共数据纯原生StyleJavaScript vue原生table 效果 原生的JavaScript原生table null 公共数据 const list [{id: "a1",title: "第一列",list: [{id: "a11",parentId: "a1",title: "第二列",list: [{ id: "…...

游戏设计模式 - 子类沙箱

核心思想 子类沙箱模式&#xff08;Subclass Sandbox&#xff09;通过将核心逻辑封装在基类中&#xff0c;为子类提供安全的"沙箱"环境。子类通过组合或重写基类提供的预定义操作来实现行为&#xff0c;而非直接操作底层系统。 这种模式在游戏开发中常用于实现角色…...

ubuntu 端口复用

需求描述&#xff1a;复用服务器的 80端口&#xff0c;同时处理 ssh 和 http 请求&#xff0c;也就是 ssh 连接和 http 访问服务器的时候都可以指定 80 端口&#xff0c;然后服务器可以正确分发请求给 ssh 或者 http。 此时&#xff0c;ssh 监听的端口为 22&#xff0c;而 htt…...