也是单调队列维护前缀和的问题。
显然我们可以维护一个序列作为前缀和。
我们这样模拟一个过程。
第一轮就是sum[1],sum[2],sum[3],sum[4],...,sum[n]中看有没有小于0的。
第二轮就是看a2,a2+a3,a2+a3+a4,...,a2+...+an+an+1中有没有小于0的。
第二轮等价于求sum[2],sum[3],sum[4],...,sum[n+1]中有没有小于sum[1]的。。。依此类推。
并且,判断每一轮是否满足条件只需要维护一个最小值了。
之后就只要用单调队列维护一个区间最小值就好了。
#include <cstdio>
#define maxn 1000006
int a[maxn<<1];
int sum[maxn<<1];
int Q[maxn<<1];
int head,tail;
void push(int i)
{
while(head<tail&&sum[Q[tail-1]]>=sum[i]) tail--;
Q[tail++]=i;
}
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
int i;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i+n]=a[i];
}
for(sum[0]=0,i=1;i<=2*n;i++)
{
sum[i]=sum[i-1]+a[i];
}
int ans=0;
head=tail=0;
for(int i=1;i<=n;i++) push(i);
if(sum[Q[head]]>=0) ans++;
//printf("%d\n",ans);
for(int i=n+1;i<2*n;i++)
{
push(i);
while(head<tail&&Q[head]<=i-n) head++;
if(sum[Q[head]]>=sum[i-n]) ans++;
}
printf("%d\n",ans);
}
return 0;
}