D. Balanced Playlist(单调队列)

 

题意:给定 n 首歌,第 i 首的值为 a[i],听完第 n 首会回到第 1 首
现在遍历 i 开始,记录听歌的最大值 a[i],如果将要听的值严格小于最大值的一半则停止,求最多听几首停止,不会停止则输出-1 

根据样例 2,可知个单循环不超过三遍,

维护一个单调递减队列,当 a[i]<q[head]/2 时,记录队首听歌的数量,当 a[i]>q[tail] 时,队尾 pop,但队尾也需要记录答案,假设队尾是 a[i-1],那么 a[i-1]<a[i] ,那么 ans[i-1]=ans[i]+1 , 因为这个题只关心最大值  

const int N=6e5+5;
 
    int n,m,t;
    int i,j,k;
    int ans[N];
    deque<Pair> d;//fr->val,sc->id
    int a[N];
void go()
{
    for(int i=1;i<=n;i++) cout<<-1<<" ";
}
int main()
{
    IOS;
    while(cin>>n){
        int minn=inf,maxx=-inf;
        for(i=1;i<=n;i++){
            cin>>a[i];
            maxx=max(maxx,a[i]);
            minn=min(minn,a[i]);
        }
        if(maxx<=2*minn) go();
        else{
            for(i=1;i<=n;i++) a[i+n]=a[i];
            for(i=n+1;i<=n+n;i++) a[i+n]=a[i];
            for(i=1;i<=n*3;i++){
                while(d.size() && d.back().fr<a[i]){
                    d.pop_back();
                }
                d.push_back(Pair{a[i],i});
                while(d.size() && d.front().fr>a[i]*2){
                    ans[d.front().sc]=i-d.front().sc;//最后一首没法听
                    d.pop_front();
                }
            }
            for(i=n*3;i;i--) if(ans[i]==0) ans[i]=ans[i+1]+1; 
            for(i=1;i<=n;i++) cout<<ans[i]<<" ";
            cout<<endl;
        }
    }
    //PAUSE;
}

 

猜你喜欢

转载自blog.csdn.net/C_Dreamy/article/details/107706755