LuoguP2629 好消息,坏消息
题面
题解
做法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位置的前缀和大