小b有一个长度为n的序列t,现在她对于每个i,求最小的正数j满足i+j<=ni+j<=n且ti+j>titi+j>ti,输出j,如果不存在这样的j,则输出0。
样例解释:
对于i=1,t2>t1t2>t1,所以最小的j=1;
对于i=7,不存在这样的j,所以输出0。
输入格式
第一行输入一个数n;(1≤n≤30000) 第二行输入n个数ti;(30≤ti≤100)
输出格式
输出一行n个数,第i个数表示i的答案。
输入样例
8
73 74 75 71 69 72 76 73
输出样例
1 1 4 2 1 1 0 0
题意简化:给定序列,问序列中每个数后面第一个比它大的在哪。
首先存在 O(n2)O(n2) 的暴力枚举。对于每个 ti,暴力找到后面第一个比它大的。
因为要找的是每个数后面第一个比它大的,所以考虑倒着做。维护一个单调减的单调栈(越靠栈顶值越小),插入当前这个数的时候不断从栈顶弹出那些小于等于它的,直到遇见一个比它大的,那么这个数就是“它后面第一个比它大的了”。
我们不妨考虑一下,这样操作为什么是合理的。如果一个数既小又靠后,那么这个数是没有什么意义的,因此被踢掉不会影响正确性。复杂度 O(n)O(n) 。
参考程序
#include<bits/stdc++.h>
using namespace std;
int n, t[30000], sum;
int main() {
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> t[i];
}
for(int i = 1; i <= n; i++) {
int sum = 0;
for(int j = 1; j<=n; j++) {
if(i + j <= n && t[i+j] > t[i]) {
cout << j << " ";
sum++;
break;
}
}
if(sum == 0) {
cout << 0 << " ";
}
}
return 0;
}