給n個數,與一個數m,求右邊最後一個至少比大的數與這個數之間有多少個數
這道題看了下其他題解都是用線段樹寫的
雖然線段樹是一個很顯然的方法,但是代碼冗長並且常數較大 (可能是我不喜歡數據結構)
如果把數據範圍開大倍就妥妥的了
這裏提供一個單調棧的打法
從後往前考慮每個位置
我們把每個答案爲的位置的數用一個遞增的單調棧維護起來
每次到一個位置就二分這個單調棧,找到第一個比它大至少的位置,然後答案就是它們的距離減
爲什麼只有的位置要放到單調棧裏面呢
因爲有比它大至少的位置,所以這個位置永遠不會是最優的
/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年09月16日 星期一 20時46分27秒
*******************************/
#include <cstdio>
#include <fstream>
using namespace std;
const int maxn = 1000006;
int n,m,mx=-1,loc,t;
int h[maxn],ans[maxn],q[maxn];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d",&h[i]);
ans[n]=-1,q[++t]=n;
for (int i=n-1;i>=1;--i){
int g=h[i]+m;
if (h[q[t]]<g){
ans[i]=-1;
if (h[q[t]]<h[i]) q[++t]=i;
}
else{
int l=1,r=t;
while (l<r){
int mid=(l+r)>>1;
if (h[q[mid]]>=g) r=mid;
else l=mid+1;
}
ans[i]=q[l]-i-1;
}
}
for (int i=1;i<=n-1;++i) printf("%d ",ans[i]);
printf("-1\n");
return 0;
}
如有哪裏講得不是很明白或是有錯誤,歡迎指正
如您喜歡的話不妨點個贊收藏一下吧