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

代码如下

//#pragma comment(linker, "/STACK:102400000,102400000")
#include
#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";
}

你可能感兴趣的:(数据结构)