CF-1237D(Balanced Playlist)

CF-1237D(Balanced Playlist)

好题

题目描述
Your favorite music streaming platform has formed a perfectly balanced playlist exclusively for you. The playlist consists of n tracks numbered from 1 to n. The playlist is automatic and cyclic: whenever track i finishes playing, track i+1 starts playing automatically; after track n goes track 1.
For each track i, you have estimated its coolness ai. The higher ai is, the cooler track i is.
Every morning, you choose a track. The playlist then starts playing from this track in its usual cyclic fashion. At any moment, you remember the maximum coolness x of already played tracks. Once you hear that a track with coolness strictly less than x/2 (no rounding) starts playing, you turn off the music immediately to keep yourself in a good mood.
For each track i, find out how many tracks you will listen to before turning off the music if you start your morning with track i, or determine that you will never turn the music off. Note that if you listen to the same track several times, every time must be counted.
输入
The first line contains a single integer n (2≤n≤105), denoting the number of tracks in the playlist.
The second line contains n integers a1,a2,…,an (1≤ai≤109), denoting coolnesses of the tracks.
输出
Output n integers c1,c2,…,cn, where ci is either the number of tracks you will listen to if you start listening from track i or −1 if you will be listening to music indefinitely.
样例输入
4
11 5 2 7
样例输出
1 1 3 2
样例输入
4
3 2 5 3
样例输出
5 4 3 6
样例输入
3
4 3 6
样例输出
-1 -1 -1
题目大意
有一个长度为n(n≤105)的循环播放歌单,每首歌有一个优秀值ai(ai≤109)。
听歌时选一首歌开始,如果某一首歌x的优秀值的两倍小于当前听过的歌中优秀值最大的,那么会在听完x之前停止听歌。
对于每首歌i,求ci表示如果从它开始听,最多听完几首歌,如果有重复的算多首。如果从一个位置开始能无限听下去,那么ci=−1。
题解
先把原数组扩大到原来的3倍。即最多最多循环3圈肯定能出答案(如果存在答案的话)
答案不存在的条件是:2*MIN>=MAX
下面讨论答案存在时,i指向当前询问的答案,pos一直右移,且维护i-pos的最大值,当满足a[pos]*2<Max时,跳出此时pos-i即为ans[i]。i+1时更新Max的值为(i+1,pos)可用rmq维护。因为i+1的答案只可能大于等于pos的值。(更新Max的值不变时,pos也不会变。Max值变小(只有可能变小)pos的值会继续右移直至出现答案)

代码如下

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#pragma GCC optimize(3,"Ofast","inline")
#define TEST freopen("C:\\Users\\hp\\Desktop\\ACM\\in.txt","r",stdin);
#define mem(a,x) memset(a,x,sizeof(a))

#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

using namespace std;
typedef long long ll;
const int INF = -1u>>1;
const int maxn=1e6+5;
int dpmin[maxn][30];    			//maxn=n   int-30 long long 60
int dpmax[maxn][30];    			//maxn=n   int-30 long long 60
int p[maxn],n;
int ans[maxn];
void rmqinit()
{
    for(int j=1; (1<<j)<=3*n; j++)
        for(int i=1; i+(1<<j)<3*n+2; i++)
        {
            dpmax[i][j]=max(dpmax[i][j-1],dpmax[i+(1<<(j-1))][j-1]);
        }
}
int rmqmax(int l,int r)
{
    int k=log(r-l+1)/log(2);
    return max(dpmax[l][k],dpmax[r-(1<<k)+1][k]);
}
int main()
{
//    mem(ans,-1);
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&p[i]);
        p[i+n]=p[i];
        p[i+2*n]=p[i];
        dpmax[i][0]=p[i];
        dpmax[i+n][0]=p[i];
        dpmax[i+2*n][0]=p[i];
    }
    int MIN=*min_element(p+1,p+n+1);
    int MAX=*max_element(p+1,p+n+1);
    if(2*MIN>=MAX)
    {
        for(int i=1; i<=n; i++)
        {
            cout<<"-1 ";
        }
        cout<<"\n";
        return 0;
    }
    rmqinit();
    int Max=p[1];
    int pos=1;
    for(int i=1; i<=n; i++)
    {
        while(!(2*p[pos]<Max))
        {
            Max=max(Max,p[pos]);
            pos++;
        }
        Max=rmqmax(i+1,pos);
        ans[i]=pos-i;
    }
    for(int i=1; i<=n; i++)
    {
        cout<<ans[i]<<" ";
    }
    cout<<"\n";
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值