欢迎光临
我们一直在努力

上海计算机学会2026年5月月赛C++丙组T4 价格的跨度

价格的跨度

题目描述

给定 NNN 个整数 A1,A2,⋯ ,ANA_1, A_2, \\cdots, A_NA1,A2,,AN,表示黄金在每天的价格。对每个 AiA_iAi,请计算并输出它的跨度。

所谓 AiA_iAi 的跨度,是指从第 iii 天开始,一天一天回溯过去的价格,直到遇到一个严格大于 AiA_iAi 的价格为止,在这个过程中经历的天数。如果在过去不存在比 AiA_iAi 更高的价格,则数到第一天为止。

输入格式

第一行:一个整数表示 NNN
第二行到第 N+1N+1N+1 行:每行一个整数表示 A1,A2,…,ANA_1, A_2, \\dots, A_NA1,A2,,AN

输出格式

NNN 行,第 iii 行有一个整数,表示 AiA_iAi 的跨度。

数据范围

1≤N≤500,0001 \\le N \\le 500,0001N500,000
1≤Ai≤1,000,000,0001 \\le A_i \\le 1,000,000,0001Ai1,000,000,000

样例

输入 #1

5
10
20
30
40
50

输出 #1

1
2
3
4
5

输入 #2

3
314
15
926

输出 #2

1
1
3

题解

这道题要求求出每个位置往前第一个严格更大的数的位置,再计算跨度,数据量最大到 50 万,暴力遍历会超时,所以我选择用单调栈来高效解题。

#include<bits/stdc++.h>
using namespace std;
int n;
// a数组:单调栈,存储价格数值
int a[1000005];
// b数组:和栈一一对应,存储对应价格的下标
int b[1000005];
// len 表示当前栈顶位置,模拟栈指针
int len=0;
int main() {
// 关闭流同步、解绑cin/cout,加速大数据读写
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// 读取总天数n
cin>>n;
// 栈底设置一个极大值,作为边界哨兵,保证所有数都能找到前驱
a[0]=1e9+5;
for(int i=1;i<=n;i++){
// 读取第i天的黄金价格
int x;
cin>>x;
// 维护单调递减栈:弹出栈顶所有 <= 当前价格的元素
// 这些元素不可能成为后面元素的"第一个更大值"
while(a[len]<=x){
len;
}
// 栈顶就是左侧第一个严格大于x的位置,计算跨度并输出
cout<<ib[len]<<"\\n";
// 当前价格和下标入栈
len++;
a[len]=x;
b[len]=i;
}
return 0;
}

解题思路

  • 题意分析
    每个位置的跨度 = 当前下标 − 左侧第一个严格大于当前价格的下标。如果左侧没有更大值,就从第一天开始算。

  • 算法选择
    数据范围 N≤5×105N \\le 5\\times 10^5N5×105,双重循环暴力查找会超时。我使用单调递减栈,每个元素只入栈、出栈各一次,整体时间复杂度 O(N)O(N)O(N),可以满足数据要求。

  • 栈设计

    • 用数组模拟栈,a[] 存价格,b[] 存对应天数下标,len 为栈顶指针。
    • 提前在栈底放一个极大值哨兵 a[0],避免判空,保证每个数都能找到结果。
  • 执行流程
    • 遍历每一天的价格,不断弹出栈顶小于等于当前价格的元素(它们不再有用)。
    • 此时栈顶元素就是左侧第一个严格更大的价格,用当前下标减去栈顶下标,得到跨度并输出。
    • 把当前价格和对应下标压入栈,继续处理下一天。
    赞(0)
    未经允许不得转载:171主机测评 » 上海计算机学会2026年5月月赛C++丙组T4 价格的跨度
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址