题目描述
传说中有一种蜜汁序列特别甜,所以爱吃甜的强渣学长特别喜欢这种序列。。。
蜜汁序列的定义如下:对于一个长度为n的序列a1,...,an,如果这个序列的n个前缀和全部非负,即若a1>=0,a1+a2>=0,...,a1+a2+...+an>=0,则称a序列是蜜汁序列。。。
显然一些蜜汁序列可以分成更多的蜜汁序列,例如1 2这个蜜汁序列可以分成1和2两个蜜汁序列,现在有一个长度为n的蜜汁序列,要求你把他分成若干连续的段,使得每段都是一个蜜汁序列,问最多可以分成多少段?
输入
多组用例,每组用例首先输入一个整数n表示给出的蜜汁序列长度,之后输入n个整数a1,a2,...,an表示该序列的n个元素,以文件尾结束输入
输出
对于每组用例,输出一个整数占一行,表示该序列最多可以分成多少个蜜汁序列
数据范围
用例不超过10组,1<=n<=10^6,-10^4<=ai<=10^4(i=1,2,...,n)
样例输入
1
1
3
1 2 3
样例输出
1
3
题解:
题目不难,读懂题目就能有个思路。问的是题目给的蜜汁序列中最多能划分成几个蜜汁序列。
因为数据范围非常大,所以如果每个数都是从a1开始一直往后数的话肯定会超时。但是注意到题目要求的是前缀和大于0,所以对于一个负数来说,要找到它所在的那个蜜汁序列,就必须要往前找,因为如果往后找的话肯定就已经不满足a1>=0了。如果有好几个负数连续,就需要从最后的那个负数开始往前倒。
一开始我写的是正序,后来就发现了问题:不知道遇到了a[n+1]>=0时是否要停止。就比如1 2 -1 -2 3 - 1 -2与2 2 -1 -2 2 -1 -2遇到第一个-1的时候不知道该不该停。所以就要从最后一个数往前数。
然后如何判断是否找到了蜜汁序列呢?方法是看这k个数总和是否大于0.如果遇到了正数,那么肯定它独自成一个序列。如果遇到了负数,就要往前找,直到这连续的k个数之和大于0为止。原因是a2--ak一定是负的,否则就不需要a1了;a3--ak也一定是负的……然后既然a1与a2--ak之和为正,且a3--ak为负,所以a1+a2也为正。以此类推……只要满足这k个数的和是正的,就能满足这是蜜汁序列。
有了如上思路,就能有一个线性遍历的算法了。但是还有一点没注意到,也就是这一点我WA了不止五发……
n是1e6,ai是1e4,稍有不慎就爆int。。。
所以必须要用long long啊orz
这序列果然很迷啊……
代码如下:
//因为一个long long 我wa了10法/微笑
#include<stdio.h>
#include<string.h>
int num[1000005];
int index = 0;
int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
index = 0;
int i = 0;
for (i = 0; i < n; i++)
scanf("%d", &num[i]);
for (i = n - 1; i >= 0; i--)
{
if (num[i] < 0)
{
long long int sum = 0;
while (sum + num[i]<0)
{
sum = sum + num[i];
i--;
}
}
index++;
}
printf("%d\n", index);
}
return 0;
}