单调队列:队首元素总是队列最小值。
此题就是把序列a先转换成前n项和,因为是循环的,所以长度为2n,然后判断一个长度为n的子序列前缀和都大于等于0,即此段序列的最小值-队列前面的和=这段序列最小的前缀和。
#include<bits/stdc++.h>
using namespace std;
#define MAX 1000000
int sum[MAX*2+1];
int mq[MAX+1];
int rear,frot;
int n;
void push(int i){
while(rear!=frot && sum[mq[rear-1]] > sum[i])
rear--;
mq[rear++]=i;
}
int main()
{
while(scanf("%d",&n)&&n)
{
for(int i=1;i<=n;i++){
scanf("%d",&sum[i]);
sum[n+i]=sum[i];
}
for(int i=2;i<=2*n;i++){
sum[i]+=sum[i-1];
}
// for(int i=1;i<=n*2;i++){
// printf("%d ",sum[i]);
// }printf("\n");
rear=frot=0;
for(int i=1;i<n;i++){
push(i);
}
// for(int i=0;i<5;i++) {
// printf("%d ",mq[i]);
// } printf("\n");
int cot=0;
for(int i=n;i<2*n;i++){
push(i);
if(mq[frot] + n - 1 < i){
frot++;
}
if(sum[mq[frot]]-sum[i-n]>=0) cot++;
}
printf("%d\n",cot);
}
return 0;
}
/*
5
-10 3 -1 5 4
*/