PAT1007
Given a sequence of K integers { N1, N2, ..., NK }.
给出一个连续的K个整数
A continuous subsequence is defined to be { Ni, Ni+1, ..., Nj } where 1 <= i <= j <= K.
一个连续的串被定义成这样{ Ni, Ni+1, ..., Nj },当1 <= i <= j <= K.
The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements.
最大的连续串是连续子串中所有元素和最大的那个
For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.
举个例子,各处一个连续串为 { -2, 11, -4, 13, -5, -2 },其中最大的子串为{ 11, -4, 13 }。它的最大和是20
Now you are supposed to find the largest sum, together with the first and the last numbers of the maxmum subsequence.
现在要求你找到最大的和,从第一个和最后一个数字
Input Specification:
Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (<= 10000). The second line contains K numbers, separated by a space.
对于每个输入文件包含一个测试用例,每个测试用例有两行,第一行包含一个整数K,第二行包含K个整数用空格分开
Output Specification:
For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence.
对于每个测试用例,输出一行,最大和的,连续子串从第一个和最后一个数字
The numbers must be separated by one space, but there must be no extra space at the end of a line.
每个数字必须用一个空格分开,但是一行的最后没有多余的空格
In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case).
在每个测试用例中最大子串不是唯一的,输出那个标记i和j最小的那个,就像用例展现的那样
If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.
如果所有的K都是负的,那么最大和被定义为0,要求你输出第一个数和最后一个数
Sample Input:
10
-10 1 2 3 4 -5 -23 3 7 -21
Sample Output:
10 1 4
首先看到这个问题就明确这是个最大子列和的变种,在求出最大子列和的同时,还要求最大子列和的头尾两个数。
遇到这种题目,我的一般思路是先把能想到的写出来,把问题先分解一下,如果单纯只是最大子列和怎么做呢?
于是我先写出下面的代码
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; int main() { int maxx=0; int temp=0; int now=0; int k; cin>>k; while (k--) { cin>>temp; now += temp; if(now < 0) { now = 0; } else { if(maxx < now) maxx = now; } } cout<<maxx; return 0; }
这样首先最大子列和最快的方式我已经知道了,是“在线处理”得出来得,时间复杂度N。
接下来的问题就是记录头尾的数了
首先要明白当最大子列和相同的时候,我们只是记录前面的,而不记录后面的,因为前面的ij肯定比后面的ij要小。
所以要更新头尾数,只能大于maxx值。
什么时候开始记录头数?
因为题目要求说,如果全部都是负数要输出最大值为0而且要输出第一个数和最后一个数,所以,一开始就要记录头数
而且当一个子列结束后,另一个子列开始要记录头数
什么时候记录尾数?
记录头数的时候就要顺便记录尾数,为什么这么说呢?因为如果整个数列只有一个正数的时候,那么输出的答案三个值都为这个正数,仔细想想为什么?
然后每次只要子列变长就要更新尾数。