D. Balanced Playlist(单调队列)

题目

题意:

    给定n张唱片,每张唱片都有一个好听度a[i]。某个人选择第i张唱片开始播放,播放完则下一张继续播放,到第n张时下一张为第1张。当某一张唱片的好听度严格小于已经听过的唱片的最大值的一半时,这个人将会停止播放。要求输出对于任意的选择一张唱片i开始,最多能听几张唱片,也可能是无穷多,这时输出-1。
     2 ≤ n ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 9 2≤n≤10^5,1≤a_i≤10^9 2n1051ai109

分析:

    思考第1张唱片停止的位置,假设为j。那么显然第二张唱片停止的位置一定是大于等于j的,因为第二张唱片开始与第一张唱片开始的区别在于第二张开始的过程中一直少了第一张的好听度,其余均一样。那么这样具有单调性的右端点,我们就可以想到划窗。由于要维护窗口的最大值,所以需要使用单调队列。由于唱片成环(需要开某些倍的数组将环变为线性结构),所以我们需要开3倍的数组(因为可能花费一圈找最大值,然后再一圈停止)。当然右端点超过3*n时自然就是停不下来的了。

#include <iostream>
using namespace std;

int a[300005],q[300005];
int ans[100005];

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n;
	cin >> n;
	int head,tail;
	head = tail = 0;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		a[i+n] = a[i];
		a[i+2*n] = a[i];
	}
	int r = 1;
	for (int i = 1; i <= n; i++)
	{
		while( head < tail && q[head] < i ) head ++;
		while( head == tail || a[r] * 2 >= a[q[head]] )
		{
			while( head < tail && a[r] >= a[q[tail-1]] ) tail --;
			q[tail] = r;
			tail ++;
			r ++;
			if( r > 3 * n ) break;
		}
		if( r > 3 * n ) ans[i] = -1;
		else ans[i] = r - i;
	}
	for (int i = 1; i <= n; i++)
	{
		cout << ans[i];
		if( i == n ) cout << '\n';
		else cout << ' ';
	}
	return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值