Codeforces 1237D. Balanced Playlist


傳送門

首先顯然的,如果一個位置開始播放了兩圈還沒結束,那么就永遠不會結束

先考慮位置 $1$ 開始播放,用一個 $multisetset$ 維護一下當前聽的所有歌,直到某一首歌 $r$ 不合法了就停止,此時播放的區間即為位置 $1$ 開始的答案

然后考慮從位置 $2$ 開始播放時和從位置 $1$ 開始播放有什么變化,顯然播放的歌曲一定可以到 $r$ (反證法容易證明),並且 $multiset$ 里少了一首位置 $1$ 的歌

那么直接把 $multiset$ 更新一下,然后繼續模擬過程直到下一個不合法,然后又可以算出答案

這樣一直算下去即可求出所有答案

均攤復雜度 $O(n \log n)$,注意要把聽歌的序列延長 $3$ 倍而不是兩倍(看樣例 $2$ 就知道了)

數組也要開 $3$ 倍!(如果你像我一樣不小心開了兩倍,那么結果就是通過 $\text{pretest}$ 然后 $WA$ 在 $\text{system test}$)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=3e5+7;
int n,n3,ans[N];
int A[N];
multiset <int> S;
int main()
{
    n=read(),n3=n*3;
    for(int i=1;i<=n;i++) A[n*2+i]=A[n+i]=A[i]=read();
    int r=1;
    for(int i=1;i<=n;i++)
    {
        while(r<=n3)
        {
            if(S.size())
            {
                int p=*S.rbegin();
                if(A[r]<p/2 || (A[r]==p/2 && p&1))
                    break;
            }
            S.insert(A[r]); r++;
        }
        ans[i]= r<=n3 ? r-i : -1; S.erase(S.find(A[i]));
    }
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    puts(""); return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM