题目描述
小鱼最近参加了一个“比可爱”比赛,参赛的鱼被从左到右排成一排,编号1~n,每只小鱼都有一个可爱值。
比赛规则如下:每只小鱼都会从它的位置开始向左边的小鱼一只一只地询问可爱值,如果询问的可爱值不大于它自己的可爱值,得分+1;如果询问的可爱值大于自己的可爱值或者左边所有小鱼可爱值都不比自己大则停止向左询问,转而从它的位置出发向右询问,询问的可爱值小于它自己的可爱值,得分+1;否则停止询问并获得最终得分。
现在作为裁判的你需要统计每一只小鱼的得分。
输入
第一行输入一个整数 n,表示鱼的数目。n<=1000000.
第二行输入 n 个整数,用空格间隔,依次表示从左到右每只小鱼的可爱程度。 小鱼的可爱程度不超过1e9。
输出
输出一行n个整数,表示每只小鱼的得分。
样例输入
5
1 2 3 4 5
样例输出
0 1 2 3 4
这里给出两种解法
解法一
单调栈的解法
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n;
int L[N],R[N],cost[N];
stack<int>s;
main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&cost[i]),R[i]=n+1;
for(int i=1;i<=n;i++) ///注意下标要从1开始,因为有些位置左边没有比他大的 L数组是0 有些位置 第一个比他大的就是0位置 L数组也是0,这种情况会导致矛盾
{
while(!s.empty()&&cost[s.top()]<=cost[i])
{
R[s.top()]=i;
s.pop();
}
s.push(i);
}
while(!s.empty()) s.pop();
for(int i=n;i>0;i--)
{
while(!s.empty()&&cost[s.top()]<cost[i])
{
L[s.top()]=i;
s.pop();
}
s.push(i);
}
for(int i=1;i<=n;i++)
printf("%d ",R[i]-L[i]-2);
}
解法二
用Next1数组来记录前一个大于它的位置,Next2数组记录后一个大于等于它的位置,求Next数组的过程有点类似求kmp中的Next数组
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int Next1[N],Next2[N];
int cost[N];
int n;
main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&cost[i]);
Next2[i]=n+1;
}
for(int i=2; i<=n; i++)
{
if(cost[i-1]>cost[i])
Next1[i]=i-1;
else
{
int j=Next1[i-1];
while(j&&cost[j]<=cost[i]) ///注意这里必须判断j不等于0
{
j=Next1[j];
}
Next1[i]=j;
}
}
for(int i=n-1; i>0; i--)
{
if(cost[i+1]>=cost[i])
Next2[i]=i+1;
else
{
int j=Next2[i+1];
while(j!=n+1&&cost[j]<cost[i]) ///注意这里必须判断j不等于n+1
{
j=Next2[j];
}
Next2[i]=j;
}
}
for(int i=1; i<=n; i++) printf("%d ",Next2[i]-Next1[i]-2);
}