单调队列—非负和

罗老师给大家n个数字:a1,a2,a3, .. , an。
这些数字可以循环,ai, ai+1, ai+2, … , an, a1, a2, … , ai-1。
显然,这样的循环有n种。
现在问大家,n种中有多少种保证从第一项到任意项的和大于等于0
比如
3
-1 1 1
有三种:
-1 1 1
1 1 -1
1 -1 1
其中第一种第一项到第1,2,3项的和分别为: -1, 0, 1
第二种第一项到第1,2,3项的和分别为: 1, 2, 1
第三种第一项到第1,2,3项的和分别为: 1, 0, 1
所以第二种和第三种符合,答案为2
输入
输入n
然后输入n个数字ai
输出
输出有多少种符合
样例输入
3
-1 1 1
样例输出
2
提示
【数据规模和约定】
1<=n<=1000000

-1000<=ai<=1000

#include<cstdio> 
#include<iostream> 
#include<algorithm> 
using namespace std; 
int n,i,t,w,ans; 
int a[2000001],sum[2000001],g[2000001],id[2000001]; 
int main() 
{ 
    cin>>n; 
    for(i=1;i<=n;i++) 
    { 
        cin>>a[i]; 
        a[i+n]=a[i]; 
    } 
    ans=0; 
    sum[0]=0; 
    for(i=1;i<=2*n;i++) sum[i]=sum[i-1]+a[i]; 
    t=1;w=1; 
    g[1]=sum[1]; 
    id[1]=1; 
    for(i=2;i<=n;i++) 
    { 
        while(sum[i]<g[w]) 
        { 
            w--; 
            if(w<t) break; 
        } 
        w++; 
        g[w]=sum[i]; 
        id[w]=i; 
    } 
    if(g[t]>=0) ans++; 
    for(i=n+1;i<=2*n-1;i++) 
    { 
        while(id[t]<i-n+1) 
        { 
            t++; 
            if(t>w) break; 
        } 
        if(w>=t) 
            while(sum[i]<g[w]) 
        { 
            w--; 
            if(w<t) break; 
        } 
        w++; 
        g[w]=sum[i]; 
        id[w]=i; 
        if(g[t]-sum[i-n]>=0) ans++; 
   
    } 
    cout<<ans<<endl; 
    return 0; 
} 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值