题目描述
给出项数为 n的整数数列 a 1 … n a_{1 … n} a1…n。
定义函数 f(i) 代表数列中第 ii 个元素之后第一个大于 a**i 的元素的下标,若不存在,则 f(i)=0。
试求出 f*(1…*n)。
CSDN显示可能有问题,不允许外链转存,大家可以在我的博客中阅读:My Blog
思路解析
实际上这一道题和前面那一道日志分析是非常像的,不过这里这个需要我们先将所有的数字都读进a[3000005],读进来之后从后往前开始,定义一个辅助数组b[3000005]用来存储相同位置的数比他大的第一个数的索引值,从最后一个数开始,最后一个数为0,然后往前,随意一个数a[i]先判断是否它比后面第一个数a[i+1]大,如果比后面第一个数a[i+1]小,那么那个辅助数组只需在该位置存储该位置的索引 i+1 就行;如果它比它后面第一个数a[i+1]大或是相等,那么就找比它后面那个数a[i+1]还大的数a[b[i+1]],由于是从后往前进行的,这个b[i+1]已经求出来了,如果我们的a[b[i+1]],仍然不比a[i]大,那么就继续找a[b[b[i+1]]], 哈哈哈,有点套娃的感觉了,实际上就是找比a[b[i+1]]还大的第一个数,这么依次找下去,直到找到一个比a[i]大的数,将其索引存储到b[i]上, 或者直到找到一个b[j]为0,那么说明a[i]是目前最大数,没有比它更大的数,那么对应的b[i]就为0。
代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int a[3000002]; // 用来存储数据
int b[3000002]; // 用来存储我们的答案
int main()
{
int n; // 总共的个数
scanf("%d", &n);
// 读取数据
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
b[n] = 0;
for (int i = n - 1; i >= 1; i--)
{
if (a[i] < a[i + 1]) // 如果后面的第一个数正好比他大
b[i] = i + 1;
else
{
int next = b[i + 1];
while (a[i] >= a[next] && next != 0) // // 如果后面第一个数没有比他更大的数,那么直接赋值为0,否则就一直找接下来的索引直到找到0或者找到合适的数为止
next = b[next];
b[i] = next;
}
}
for (int i = 1; i <= n; i++)
printf("%d ", b[i]);
return 0;
}