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

牛客周赛 Round 104(小红的树不动点)

小红的树不动点

跟E题有类似当i为不动点时,1-i-1个数都必须在区间内,但此时是在树上的话就改为公共祖先相同,所以他是不动点的条件就为根节点就为他们的公共祖先,所以i成立的树就有1-i的lca的深度个。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <bits/stdc++.h>
#define ll long long 
using namespace std;int n;  // 树的节点数
vector<vector<int>> a;  // 邻接表存储树结构
int shu[200005][18];    // 倍增表:shu[i][j]表示节点i的第2^j级祖先
int head[200005];       // head[i]存储节点i的深度(距根节点的距离)
int logn[200005];       // 对数表:logn[i] = floor(log2(i))
bool b[200005];         // DFS访问标记数组// 深度优先搜索初始化树结构
void dfs(int h, int k) {b[h] = true;        // 标记当前节点已访问head[h] = k;        // 记录当前节点的深度kfor (int i = 0; i < a[h].size(); i++) {if (!b[a[h][i]]) {             // 遍历未访问的邻接节点shu[a[h][i]][0] = h;       // 记录直接父节点(2^0级祖先)dfs(a[h][i], k + 1);       // 递归访问子节点,深度+1}}
}// 预处理倍增表和log表
void chu() {// 初始化对数数组(避免重复计算log)logn[1] = 0;logn[2] = 1;for (int i = 3; i <= n; i++) {logn[i] = logn[i / 2] + 1;  // 递推计算log2(i)的整数部分}// 构建倍增表(核心预处理)for (int j = 1; (n >> j) > 0; j++) {  // j: 2^j不超过总节点数for (int i = 1; i <= n; i++) {if (shu[i][j - 1] != 0) {     // 确保祖先存在// 倍增递推:2^j级祖先 = 2^{j-1}级祖先的2^{j-1}级祖先shu[i][j] = shu[shu[i][j - 1]][j - 1];}}}
}// 基于倍增法查询最近公共祖先(LCA)
int lca(int l, int r) {// 确保r是较深的节点[5,10](@ref)if (head[l] > head[r]) swap(l, r);// 将较深节点r提升到与l同深[9](@ref)int q = head[r] - head[l];while (q != 0) {r = shu[r][logn[q]];  // 按2的幂次跳跃[11](@ref)q -= 1 << logn[q];    // 更新剩余深度差}// 若提升后重合,直接返回[4](@ref)if (l == r) return l;// 同步向上跳跃至LCA下方[3,10](@ref)for (int j = (int)log2(n); j >= 0; j--) {if (shu[l][j] != shu[r][j]) {  // 祖先不同才跳跃l = shu[l][j];r = shu[r][j];}}return shu[l][0];  // 返回最终公共祖先
}int main() {ios::sync_with_stdio(false);  // 禁用C与C++流同步cin.tie(nullptr);             // 解除cin与cout的绑定// 输入树结构cin >> n;a.resize(n + 1);int l, r;for (int i = 0; i < n - 1; i++) {cin >> l >> r;a[l].push_back(r);  // 无向图双向连接a[r].push_back(l);}// 从节点n开始DFS(此处根节点设为n)dfs(n, 1);  // 参数:起始节点n,初始深度1chu();      // 预处理倍增表ll sum = 0;int x = 1;  //1-i的lca;for (int i = 1; i <= n; i++) {if (i > 1) x = lca(x, i);  // 计算当前x与i的LCAsum += head[x];             // 累加LCA的深度,及答案}cout << sum << endl;return 0;
}

http://www.dtcms.com/a/336709.html

相关文章:

  • 人工智能入门②:AI基础知识(下)
  • 计算机程序编程软件开发设计之node..js语言开发的基于Vue框架的选课管理系统的设计与实现、基于express框架的在线选课系统的设计与实现
  • STM32——软硬件I2C
  • Font Awesome Kit 使用详解
  • OTA升级
  • Vue Router 嵌套路由与布局系统详解:从新手到精通
  • 【牛客刷题】随机加减操作:两种高效解法详解(DFS记忆化搜索和动态规划集合更新法)
  • java序列化和反序列化
  • FX10/20 (CYUSB401X)开发笔记5 固件架构
  • 【个人项目】跑者天地—测试报告
  • 深入解析二维数组传参的本质
  • 运动场和光流-动手学计算机视觉17
  • 正则表达式实用面试题与代码解析专栏
  • 【Nginx】限流设置
  • 二三层交换转发业务~基础汇总
  • Mysql笔记-错误条件\处理程序
  • SSM从入门到实践:1.1 Spring框架概述与IoC容器入门
  • 堆(Heap):高效的优先级队列实现
  • duiLib 解决点击标题栏中按钮无响应问题
  • ROS2基础
  • C语言零基础第19讲:自定义类型—联合体和枚举
  • 解锁Java开发神器:XXL-Job从入门到精通
  • BT_LE_ADV_CONN_ONE_TIME 参数详解
  • Spring 创建 Bean 的 8 种主要方式
  • [创业之路-556]:创新的本质是赚不确定性带来的潜在价值,把不确定性逐步转化确定性,周而复始。
  • 产品设计.Ai产品经理
  • 48.Seata认识、部署TC服务、微服务集成
  • 网络中的一些基本概念
  • Conda 环境 在AI 私有化部署 有怎么用?
  • 微信小程序 小白gps工具v0.01 使用说明