解题思路:维护一个单调递减的栈,每当当前元素大于栈顶,则说明当前元素是第一个大于栈顶元素的元素;此时,将栈内小于当前元素的元素全部弹出,然后将当前元素压入栈顶,维护栈的单调性。
例如:单调栈内是 5 3 2, 当前元素是4(即5 3 2 4...的序列),那么应该将栈内小于当前元素的元素全部弹出,(先将栈顶2弹出,并设大于2的第一个元素是5;然后先将栈顶3弹出,并设大于的第一个元素是5),最后4小于栈顶5,不再弹栈,然后将4压入栈,此时栈内为5 4,继续遍历后面的数字。
#include<iostream>
using namespace std;
const int N = 3e6 + 5;
int num[N];//存放输入的数组
int stack[N];//单调栈,存的是num数组的下标
int ans[N];//结果数组,存放的也是num的下标
int n;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &num[i]);
//数组从1开始存,便于处理元素
int t = 0;//栈顶指针,指向的是栈内下一个被存入的位置
for (int i = 1; i <= n; i++)
{
while (t && num[i] > num[stack[t - 1]])//若当前元素大于栈顶
{
t--;//弹栈
ans[stack[t]] = i;//设当前元素为大于栈顶的第一个元素
}
stack[t++] = i;//将当前元素压栈
}
for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
return 0;
}