Codeforces 1237D. Balanced Playlist
2024-10-06 20:58:24
首先显然的,如果一个位置开始播放了两圈还没结束,那么就永远不会结束
先考虑位置 $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=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=3e5+;
int n,n3,ans[N];
int A[N];
multiset <int> S;
int main()
{
n=read(),n3=n*;
for(int i=;i<=n;i++) A[n*+i]=A[n+i]=A[i]=read();
int r=;
for(int i=;i<=n;i++)
{
while(r<=n3)
{
if(S.size())
{
int p=*S.rbegin();
if(A[r]<p/ || (A[r]==p/ && p&))
break;
}
S.insert(A[r]); r++;
}
ans[i]= r<=n3 ? r-i : -; S.erase(S.find(A[i]));
}
for(int i=;i<=n;i++) printf("%d ",ans[i]);
puts(""); return ;
}
最新文章
- JDBC Tutorials: Commit or Rollback transaction in finally block
- lodop打印控件
- webDriver 执行杀死浏览器进程方法
- Java日志规范
- PHP FastCGI RCE Vul
- poj 2001:Shortest Prefixes(字典树,经典题,求最短唯一前缀)
- 2016.8.16 JQuery学习记录
- 关于ubuntu 系统
- day55
- .Net 4.0特性 Tuple元组
- Poj 3517 And Then There Was One Joseph核心问题
- knockout笔记
- To the end
- phpcms笔记
- springmvc常用注解标签详解【转】
- 【可视化】Echarts3坐标系倒映
- svn conflict 冲突解决
- 洛谷P3168 [CQOI2015]任务查询系统
- Java 8中用法优雅的Stream,性能也";优雅";吗?
- python 回溯法 子集树模板 系列 —— 13、最佳作业调度问题