XKC's basketball team【单调队列】

题意:

给定一个序列,从每一个数后面比它大至少 \(m\) 的数中求出与它之间最大的距离。如果没有则为 \(−1\)
题目链接:https://nanti.jisuanke.com/t/41387

分析:

  从后向前维护一个递增的队列,从后往前遍历,若当前的数大于队尾就进队,否则从该队列中二分找最小的比自己大至少 \(m\) 的数(因为是从后向前维护,所以先找的一定最优),二者之间的距离即为答案。若当前数小于队尾,那这个数一定没有队尾的数优,因为它既比队尾的数靠前,又比它小。
时间复杂度:\(O(nlogn)\)

代码:

#include <bits/stdc++.h>

using namespace std;
const int N=5e5+5;
int w[N],q[N],ans[N],pos[N];
int main()
{
    int n,m,cnt=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);
    for(int i=n;i>=1;i--)
    {
        if(cnt>0)
        {
            int t=lower_bound(q+1,q+1+cnt,w[i]+m)-q;
            if(t>cnt)
            {
                ans[i]=-1;
                t=lower_bound(q+1,q+1+cnt,w[i])-q;//队列中维护递增
                if(t>cnt)
                {
                    q[++cnt]=w[i];
                    pos[cnt]=i;//记录在原数组中的位置
                }
            }
            else
                ans[i]=pos[t]-i-1;
        }
        else
        {
            ans[i]=-1;
            q[++cnt]=w[i];
            pos[cnt]=i;
        }
    }
    for(int i=1;i<=n;i++)
        printf("%d%c",ans[i],i==n?'\n':' ');
    return 0;
}

posted @ 2020-07-01 10:12  xzx9  阅读(112)  评论(0编辑  收藏  举报