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

P13019 [GESP202506 八级] 树上旅行

解题思路

这个问题需要在有根树上模拟移动操作,但直接模拟会超时(因为移动次数可能很大)。核心思想是使用二进制提升(Binary Lifting)技术来优化移动过程。

关键观察:

  1. 向上移动(移动到父节点):可以使用倍增表 f[i][j] 表示从节点 i 向上移动 2^j 步到达的节点

  2. 向下移动(移动到最小子节点):可以使用倍增表 d[i][j] 表示从节点 i 向下移动 2^j 步(每次都走最小子节点)到达的节点

算法步骤:

  1. 预处理:构建两个倍增表

    • f[i][j]:向上移动的倍增表

    • d[i][j]:向下移动的倍增表

  2. 查询处理:对于每个移动序列,使用倍增表快速计算最终位置

#include<bits/stdc++.h>
#define ll long long
using namespace std;const int N = 2e5 + 10, inf = 0x3f3f3f3f;
int n, q;
vector<int> g[N];  // 存储每个节点的子节点
int fa[N], son[N]; // 父节点和子节点信息
int f[N][25];      // 向上移动的倍增表:f[i][j] 表示从i向上移动2^j步到达的节点
int dep[N], d[N][25]; // d[i][j] 表示从i向下移动2^j步(走最小子节点)到达的节点// DFS预处理倍增表
void dfs(int x, int fat)
{// 初始化向上移动的倍增表f[x][0] = fat;for(int i = 1; i <= 20; i++){int y = f[x][i - 1];f[x][i] = f[y][i - 1];  // 倍增:2^i = 2^(i-1) + 2^(i-1)
    }// 递归处理子节点for(int i = 0; i < g[x].size(); i++){int y = g[x][i];dfs(y, x);}// 初始化向下移动的倍增表if(g[x].size() >= 1) d[x][0] = g[x][0];  // 第一步向下移动到最小子节点else d[x][0] = x;        // 叶子节点无法向下移动// 构建向下移动的倍增表for(int i = 1; i <= 20; i++){int y = d[x][i - 1];d[x][i] = d[y][i - 1];  // 倍增原理
    }
}// 向上移动op步
int up(int s, int op)
{// 使用二进制分解快速计算for(int i = 20; i >= 0; i--){if(op >= (1 << i)){  // 如果剩余步数 >= 2^iop -= (1 << i);s = f[s][i];     // 一次性移动2^i步
        }}return max(s, 1);  // 保证不会移动到根节点之上
}// 向下移动op步(沿着最小子节点路径)
int down(int s, int op)
{// 如果是叶子节点,无法向下移动if(d[s][0] == s) return s;// 使用二进制分解快速计算for(int i = 20; i >= 0; i--){if(op >= (1 << i)){  // 如果剩余步数 >= 2^iop -= (1 << i);s = d[s][i];     // 一次性向下移动2^i步
        }}return s;
}int main()
{cin >> n >> q;// 读入树结构for(int i = 2; i <= n; i++){int x; cin >> x;g[x].push_back(i);  // 添加子节点fa[i] = x;          // 记录父节点
    }// 对每个节点的子节点排序,确保第一个是最小编号的子节点for(int i = 1; i <= n; i++) sort(g[i].begin(), g[i].end());fa[1] = 1;  // 根节点的父节点设为自身dfs(1, 0);  // 从根节点开始DFS预处理// 处理每个查询while(q--){int s, k; cin >> s >> k;  // 起点和移动序列长度for(int i = 1; i <= k; i++){int op; cin >> op;  // 移动操作if(op > 0) s = up(s, op);    // 向上移动else s = down(s, -op); // 向下移动(取绝对值)
        }cout << s << endl;  // 输出终点
    }return 0;
}

 

http://www.rkmt.cn/news/13047.html

相关文章:

  • 完整教程:负载均衡式的在线OJ项目编写(二)
  • 记录这辈子见到的第一道从上到下的树上倍增
  • 06.容器存储 - 教程
  • 深入解析:【Linux】进程概念(六):进程地址空间深度解析:虚拟地址与内存管理的奥秘
  • 深入解析:Metal - 5.深入剖析 3D 变换
  • 油猴脚本(tampermonkey)离线安装文件下载,带油猴(tampermonkey)插件清单
  • 详细介绍:【汽车篇】基于深度学习的2D+3D整车漆面外观缺陷检测
  • 深入解析:网线传输距离限制 | 理论基础 / 实际应用 | 双绞线分类与特性 / 水晶头制作
  • 2025年试验机品牌权威推荐榜:聚焦 TOP5 专精特新企业,疲劳试验机,压力试验机,液压万能试验机等设备技术实力与口碑解析!
  • [2025.9.27鲜花] 私たちもう一生 分かり合えないと 分かっていたでしょう
  • 2025年岗亭厂家最新权威推荐榜:内蒙古门卫室岗亭,售货岗亭,值班岗亭,保安岗亭,低噪声岗亭选购指南
  • SPI和普通设计模式区别
  • 混元开源之力:spring-ai-hunyuan 项目功能升级与实战体验 - 指南
  • 【题解】P13345 [EGOI 2025] IMO
  • 详细介绍:Python高效合并Excel多Sheet工作表,告别繁琐手动操作
  • Python爬虫的实现流程
  • 自动化运维工具 Ansible 集中化管理服务器 - 实践
  • 2025 北京羊蝎子餐厅推荐排行榜:TOP3最新必吃榜单,聚焦朝阳昌平东城等区域,揭秘北京羊蝎子餐厅必吃的门店!
  • Eurocrypt 2021 s Accepted Papers
  • Python 输入、输出的用法
  • 劝娃妈和娃不要学老人坐姿有感:老人无奈才坐成那样的。。AI协助分析很到位
  • 从“看得见”到“能决策”:Operation Intelligence 重构企业智能运维新范式 - 实践
  • 集训队互测投题——封印
  • Docker基础与工程部署
  • 安装MariaDB服务器流程介绍在Ubuntu 22.04系统
  • 三种神器让LLM输出结构化数据:LangChain、LlamaIndex与Function Calling实战指南
  • win11安装ensp
  • 无刷电机驱动工程及PID算法FOC算法完成(超高质量超高质量
  • 35Bourbaki1-1@《数学原理》1-1@20250927
  • Crypto 2021 s Accepted papers