题目链接
https://codeforces.com/problemset/problem/92/D
题意
给n个数,问每个数后最远的比他小的数跟他的距离减1,不存在为-1
思路
看题钻逆序牛角尖了,仔细分析一下,从后往前看,对于ai和aj,如果i<j但ai>aj,显然ai一点用没有。因为他不可能产生比aj更优的答案。因此从后往前维护一个递减的单调栈,如果当前数字比栈顶小,压栈,答案为-1,否则根据刚刚分析的,它不会令答案更优,直接二分搜它的答案即可,不用压入栈。
教训/收获
单调栈,单调队列。它们的核心在于单调,我们压队列压栈的时候很多都是从前向后或者从后向前,我们利用类似刚才的思路,检查是否有这种单调的性质,那么就可以尝试这两个数据结构
代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#include<set>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=200505;
const int inf=0x3f3f3f3f;
int n,m,k;
int a[maxn];
int ans[maxn];
int id[maxn],num[maxn];
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int cnt=1;
for(int i=n;i;i--){
if(cnt==1||num[cnt-1]>=a[i]){
ans[i]=-1;
id[cnt]=i;
num[cnt++]=a[i];
}
else{
int l=1,r=cnt-1,mid;
while(l<r){
mid=(l+r)/2;
if(num[mid]>=a[i]){
l=mid+1;
}
else{
r=mid;
}
}
ans[i]=id[r]-i-1;
}
}
for(int i=1;i<=n;i++)
cout<<ans[i]<<' ';
cout<<endl;
}