LuoguP2629 好消息,坏消息

LuoguP2629 好消息,坏消息

题面

P2629

题解

做法1:

显然,题目要求求有多少个位置K使得任意N>=i>=K满足sum[i]-sum[k]>=0且任意1<=i<=k-1满足sum[i]+sum[n]-sum[k-1]>=0

所以当枚举任意一个K的时候,只要记录k~n的前缀和最小值满足及1-k-1的前缀和满足条件即是一组解

代码如下:

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 1000000 + 10;

inline int read()
{
    int f=1,x=0;
    char ch;
    do
    {
        ch=getchar();
        if(ch=='-') f=-1;
    }while(ch<'0'||ch>'9');
    do
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }while(ch>='0'&&ch<='9');
    return f*x;
}

int n;
int a[MAXN];
int sum[MAXN];
int prem[MAXN],prem1[MAXN];
int minn,maxn;

int main()
{
    memset(prem,127,sizeof(prem));
    memset(prem1,127,sizeof(prem1));
    n=read();minn=1<<30;maxn=-(1<<30);
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=n;i++)
    {
        sum[i]=sum[i-1]+a[i];
        minn=min(minn,sum[i]);
        maxn=max(maxn,sum[i]);
    }
    int res=0;
    for(int i=1;i<=n;i++) prem[i]=min(prem[i-1],sum[i]);
    for(int i=n;i>=1;i--) prem1[i]=min(prem1[i+1],sum[i]);
    for(int k=1;k<=n;k++)
    {    
        int max1=sum[k-1];
        int max2=sum[n]-sum[k-1];
        if(prem1[k]-max1>=0&&max2+prem[k]>=0) res++;
    }
    cout<<res<<endl;
}

做法2:

看一看Luogu题解

发现可以单调队列搞一搞

破环为链,把数列扩大一倍

问题转化为在长度为K的区间中的最小值有没有K-1位置的前缀和大

posted @ 2019-07-08 15:24  Randyhoads  阅读(145)  评论(0)    收藏  举报