2629 好消息,坏消息!
知道这些信息的好坏度,研究如何不让老板发怒
题意很好理解,给定一个序列,使得这个序列的和不能为负数的方案,很显然,和前缀和单调队列有关系
而且我发现,单调队列和前缀和经常在一起考,并且前缀和这个东西在提高组的有很大的用武之地
对于这个题很显然,一个数列有很多种情况,也很显然,这个题又是一个破环为链的操作
对于破环为链的操作我们已经很熟悉了,需要开两倍的空间
要想让uim同学不被炒鱿鱼,我们只能让这个区间内的和为正数,熟悉前缀和的肯定会明白如何计算区间和,那么这个题其实就没有什么了…吧
我们还需要用单调队列来维护,最后判断区间和是否合法
还有一个小小的bug,我调了好长时间,啊啊啊,我把&&打成了&&&,导致调了一个小时呜呜呜
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int SIZE=2e6+5;
int n;int head=1,tail;int ans;
ll a[SIZE];
ll sum[SIZE];
ll q[SIZE];
int main()
{
cin>>n;
for(register int i=1;i<=n;i++)//输入n个数
cin>>a[i];
for(register int i=1;i<=n-1;i++)
a[i+n]=a[i];//破环为链
for(register int i=1;i<=2*n-1;i++)
sum[i]=sum[i-1]+a[i];//计算前缀和
for(register int i=1;i<=2*n-1;i++)
{
while(head<=tail&&max(i-n+1,1)>q[head]) head++;//判断窗口长度
while(head<=tail&&sum[i]<=sum[q[tail]]) tail--;//不满足单调性出列
q[++tail]=i;
if(i-n+1>0&&sum[q[head]]-sum[i-n]>=0) ans++;//计算答案
}
cout<<ans<<endl;
return 0;
}