尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

UVa 12674 Go up the Ultras

UVa 12674 Go up the Ultras
📅 发布时间:2026/6/19 13:12:08

问题描述

给定一个山脉的二维剖面,由NNN个点组成,每个点有一个海拔高度HiH_iHi​(单位:厘米)。 我们需要找出所有Ultras\texttt{Ultras}Ultras山峰,即那些地形突出度(topographic prominence\texttt{topographic prominence}topographic prominence)大于等于150000150000150000厘米的山峰。

地形突出度的定义

对于海拔为hhh的山峰ppp,其突出度定义为最大的ddd,使得从ppp到任意更高山峰的任何路径都必须经过一个海拔为h−dh-dh−d的点。 如果没有更高的山峰,则突出度就是hhh本身。

输入格式

  • 第一行:整数NNN(3≤N≤1053 \leq N \leq 10^53≤N≤105),表示点数。
  • 第二行:NNN个整数HiH_iHi​(0≤Hi≤1060 \leq H_i \leq 10^60≤Hi​≤106),表示按顺序排列的各点海拔。
  • 相邻点海拔不同(Hi≠Hi+1H_i \neq H_{i+1}Hi​=Hi+1​)。
  • 第一个和最后一个点在海平面(H1=HN=0H_1 = H_N = 0H1​=HN​=0)。
  • 保证至少有一个Ultra\texttt{Ultra}Ultra。

输出格式

输出所有Ultras\texttt{Ultras}Ultras的索引(按出现顺序, 从111开始编号)。


题目分析

这个问题本质上是计算每个山峰的地形突出度,然后筛选出满足条件的山峰。 关键在于如何高效地计算突出度。

突出度计算的核心

对于位置iii的山峰(海拔H[i]H[i]H[i]):

  1. 向左寻找:找到左边第一个严格更高的山峰位置LLL。 在区间(L,i)(L, i)(L,i)中找到最低海拔点,记为leftMinleftMinleftMin。 如果左边没有更高山峰,则leftMin=0leftMin = 0leftMin=0(可以下降到海平面)。
  2. 向右寻找:找到右边第一个严格更高的山峰位置RRR。 在区间(i,R)(i, R)(i,R)中找到最低海拔点,记为rightMinrightMinrightMin。 如果右边没有更高山峰,则rightMin=0rightMin = 0rightMin=0。
  3. 计算突出度:
    • 如果左右都没有更高山峰(即LLL和RRR都不存在),则突出度prominence=H[i]prominence = H[i]prominence=H[i]。
    • 否则,突出度prominence=H[i]−max⁡(leftMin,rightMin)prominence = H[i] - \max(leftMin, rightMin)prominence=H[i]−max(leftMin,rightMin)。
  4. 判断 $\texttt{Ultra}¥:如果prominence≥150000prominence \geq 150000prominence≥150000,则iii是Ultra\texttt{Ultra}Ultra。

算法设计要点

  1. 寻找左右第一个更高山峰:

    • 可以使用单调栈。 从左到右扫描,维护一个单调递减栈(严格来说是非递增,但要注意是“严格更高”,所以弹出条件是H[栈顶]≤H[i]H[栈顶] \leq H[i]H[栈顶]≤H[i])。
    • 同理,从右到左扫描得到右边第一个更高山峰。
  2. 查询区间最小值:

    • 需要快速查询任意区间[l,r)[l, r)[l,r)的最小海拔值。
    • 由于NNN最大为10510^5105,不能使用O(n2)O(n^2)O(n2)的暴力方法。
    • 可以使用RMQ(Range Minimum Query)\texttt{RMQ(Range Minimum Query)}RMQ(Range Minimum Query)预处理,实现O(1)O(1)O(1)查询。
    • 这里采用稀疏表(Sparse Table\texttt{Sparse Table}Sparse Table)实现RMQ\texttt{RMQ}RMQ,预处理O(nlog⁡n)O(n \log n)O(nlogn),查询O(1)O(1)O(1)。
  3. 边界处理:

    • 第一个和最后一个点是海平面(高度000),不计入山峰。
    • 注意“严格更高”意味着海拔必须大于当前山峰,相等不算。
    • 当左右都没有更高山峰时,突出度等于自身高度。

算法步骤

  1. 读入数据。
  2. 使用单调栈计算每个位置左边第一个更高山峰的位置leftHigher[i]leftHigher[i]leftHigher[i]和右边第一个更高山峰的位置rightHigher[i]rightHigher[i]rightHigher[i]。
  3. 构建稀疏表,用于快速查询任意区间的最小海拔值。
  4. 遍历每个位置iii(从111到N−2N-2N−2,排除首尾海平面点):
    • 查询leftMinleftMinleftMin:如果leftHigher[i]≠−1leftHigher[i] \neq -1leftHigher[i]=−1,查询区间(leftHigher[i],i)(leftHigher[i], i)(leftHigher[i],i)的最小值;否则leftMin=0leftMin = 0leftMin=0。
    • 查询rightMinrightMinrightMin:如果rightHigher[i]≠NrightHigher[i] \neq NrightHigher[i]=N,查询区间(i,rightHigher[i])(i, rightHigher[i])(i,rightHigher[i])的最小值;否则rightMin=0rightMin = 0rightMin=0。
    • 计算突出度。
    • 如果突出度≥150000\geq 150000≥150000,记录索引。
  5. 输出结果。

复杂度分析

  • 单调栈扫描:O(N)O(N)O(N)
  • 稀疏表构建:O(Nlog⁡N)O(N \log N)O(NlogN)
  • 查询与遍历:O(N)O(N)O(N)
  • 总复杂度:O(Nlog⁡N)O(N \log N)O(NlogN),可以处理N≤105N \leq 10^5N≤105的数据规模。

代码实现

// Go up the Ultras// UVa ID: 12674// Verdict: Accepted// Submission Date: 2025-12-24// UVa Run Time: 0.100s//// 版权所有(C)2025,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;intmain(){ios::sync_with_stdio(false);cin.tie(nullptr);intn;while(cin>>n){vector<int>h(n);for(inti=0;i<n;i++)cin>>h[i];// 左边第一个严格更高的位置vector<int>leftHigher(n,-1);stack<int>st;for(inti=0;i<n;i++){while(!st.empty()&&h[st.top()]<=h[i])st.pop();if(!st.empty())leftHigher[i]=st.top();st.push(i);}// 右边第一个严格更高的位置while(!st.empty())st.pop();vector<int>rightHigher(n,n);for(inti=n-1;i>=0;i--){while(!st.empty()&&h[st.top()]<=h[i])st.pop();if(!st.empty())rightHigher[i]=st.top();st.push(i);}// 构建稀疏表(RMQ)用于快速查询区间最小值intlogn=1;while((1<<logn)<=n)logn++;vector<vector<int>>minTable(logn,vector<int>(n));for(inti=0;i<n;i++)minTable[0][i]=h[i];for(intk=1;k<logn;k++)for(inti=0;i+(1<<k)<=n;i++)minTable[k][i]=min(minTable[k-1][i],minTable[k-1][i+(1<<(k-1))]);// 区间最小值查询函数autorangeMin=[&](intl,intr){if(l>=r)returnINT_MAX;intk=31-__builtin_clz(r-l);returnmin(minTable[k][l],minTable[k][r-(1<<k)]);};// 计算每个山峰的突出度并找出 Ultrasvector<int>ultras;for(inti=1;i<n-1;i++){intleftMin=0;if(leftHigher[i]!=-1)leftMin=rangeMin(leftHigher[i]+1,i);intrightMin=0;if(rightHigher[i]!=n)rightMin=rangeMin(i+1,rightHigher[i]);intprominence;if(leftHigher[i]==-1&&rightHigher[i]==n)prominence=h[i];elseprominence=h[i]-max(leftMin,rightMin);if(prominence>=150000)ultras.push_back(i+1);}// 输出结果if(!ultras.empty()){cout<<ultras[0];for(size_t i=1;i<ultras.size();i++)cout<<" "<<ultras[i];}cout<<"\n";}return0;}

总结

本题的关键在于理解地形突出度的定义,并将其转化为可计算的算法。 通过单调栈快速找到每个山峰左右第一个更高山峰,再结合RMQ\texttt{RMQ}RMQ快速查询区间最小值,即可高效计算出每个山峰的突出度。 算法复杂度O(Nlog⁡N)O(N \log N)O(NlogN),完全满足题目要求。

需要注意的细节包括:

  1. “严格更高”意味着海拔必须大于,不能等于。
  2. 当没有更高山峰时,突出度等于自身高度。
  3. 海平面点(高度000)不计入山峰。
  4. 区间查询时注意边界处理。

这个问题的解法综合运用了单调栈和稀疏表两种数据结构,是一道很好的练习题目。

相关新闻

  • 如何获取高质量语音样本用于GPT-SoVITS训练?
  • 5、工作流开发:异常处理与内置活动扩展
  • 用AIGC构建测试知识库:自动问答系统解答团队常见测试问题

最新新闻

  • o3-mini作为工程协作者的ML项目落地实践
  • ONNX工程化落地:从模型转换到边缘部署的全链路实践
  • 5个鼠标魔法技巧:让普通鼠标在macOS上超越苹果触控板的完整指南
  • windows权限划分
  • OpenSpeedy:3分钟学会使用开源游戏加速工具,告别卡顿延迟
  • DeepSeek效率革命:大模型推理优化与工程化落地实践

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号