题目描述
滑稽果被排成一列, poison 的 lsr 要求每个顾客只能买一段连续的区间。
sxd 来这里买滑稽果,他对每个滑稽果都有一个喜爱程度 Ai 是一个整数,-100≤Ai≤100,
并保证∑Ai <=2147483647, 最终的满意度为所有他买到的滑稽果的喜欢程度之和, 如果和
为正(不管是正多少, 只要大于 0 即可) , 则他满意了。
现在 sxd 想知道在他满意的条件下最多能买到多少滑稽果。
输入描述
第一行一个正整数 n, 表示 lsr 一共摘了 n 个滑稽果。
第二行 n 个整数, 每个整数 Ai 表示 sxd 第 i 个滑稽果的喜爱程度为多少。
输出描述
一行一个正整数 ans 表示在 sxd 满意的条件下最多能买到多少滑稽果
输入样例
5 0
0 -7 -6 1
输出样例
1
数据范围及提示
对于 30%的数据, n<=510^3
对于 60%的数据, n<=10^5
对于所有数据, n<=310^7
请注意本题的内存限制, 完成代码后请务必计算一下你程序的内存是否超限。
由于本题的输入过大, 请必须使用基于 fread 的输入模板, 见题目目录下的 fastIO.cpp
神奇的题目 奇妙的解法···这是一道神奇的题目
首先给出暴力解法
#include <iostream>
#include <cstdio>
#include <cmath>
#pragma GCC optimize(3)
using namespace std;
int a[50000005],len[50000005];
int sum[50000005];
int maxlen;
inline char gc()
{
static char buf[1<<12],*p1=buf,*p2=buf;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<12,stdin),p1==p2)?EOF:*p1++;
}
#define dd c = gc()
inline int read()
{
static int x;
x = 0;
int dd;
bool f = false;
for(; !isdigit(c); dd)
if(c == '-')
f = true;
for(; isdigit(c); dd)
x = (x<<1) + (x<<3) + (c^48);
if(f)
x = -x;
return x;
}
#undef dd
int main() {
freopen("trade.in","r",stdin);
freopen("trade.out","w",stdout);
long n;
//scanf("%d",&n);
n=read();
for(int i=1;i<=n;i++)
{
//scanf("%d",&a[i]);
a[i]=read();
sum[i]=sum[i-1]+a[i];
for(int j=0;j<=i;j++)
{
if(sum[i]-sum[j]>0&&i-j>maxlen) maxlen=i-j;
}
}
printf("%d",maxlen);
return 0;
}
明眼人一看数据范围就知道
这肯定超时了
然后我也没思路了 再然后就是其他大佬的指导了
大佬说首先简化一下
把查询的时间复杂度降下来
求出从i到n范围内的最大值
这样就是一个有序的单调的数列了
for(int i=n;i>=1;i--)
{
maxx[i]=max(maxx[i+1],sum[i]);
}
从左往右开始扫描
当右指针所在的最大值小于左指针所在的前缀和
那么表示右指针右边的值的和小于0符合条件是
右指针向右扫描
直到右指针所处位置的最大值小于等于左指针的前缀和
然后代码如下
for(int l=1,r=1;l<=n&&r<=n;l++,r++){
if(maxx[r]<=sum[l-1])
continue;
while(maxx[r]>sum[l-1]&&r<=n){
r++;
}
ans=max(ans, r-l);
}
最后总结一下就是
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int maxx[30000005];
int sum[30000005];
int ans=0;
inline char gc()
{
static char buf[1<<12],*p1=buf,*p2=buf;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<12,stdin),p1==p2)?EOF:*p1++;
}
#define dd c = gc()
inline int read()
{
static int x;
x = 0;
int dd;
bool f = false;
for(; !isdigit(c); dd)
if(c == '-')
f = true;
for(; isdigit(c); dd)
x = (x<<1) + (x<<3) + (c^48);
if(f)
x = -x;
return x;
}
#undef dd
int main() {
freopen("trade.in","r",stdin);
freopen("trade.out","w",stdout);
memset(maxx, -0x3f3f3f3f, sizeof(maxx));
int n;
n=read();
for(int i=1;i<=n;i++)
{
sum[i]=read();
sum[i]+=sum[i-1];
}
for(int i=n;i>=1;i--)
{
maxx[i]=max(maxx[i+1],sum[i]);
}
for(int l=1,r=1;l<=n&&r<=n;l++,r++){
if(maxx[r]<=sum[l-1])
continue;
while(maxx[r]>sum[l-1]&&r<=n){
r++;
}
ans=max(ans, r-l);
}
printf("%d",ans);
return 0;
}