Max Sum of Max-K-sub-sequence
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
Given a circle sequence A[1],A[2],A[3]......A[n]. Circle sequence means the left neighbour of A[1] is A[n] , and the right neighbour of A[n] is A[1].
Now your job is to calculate the max sum of a Max-K-sub-sequence. Max-K-sub-sequence means a continuous non-empty sub-sequence which length not exceed K.
Now your job is to calculate the max sum of a Max-K-sub-sequence. Max-K-sub-sequence means a continuous non-empty sub-sequence which length not exceed K.
Input
The first line of the input contains an integer T(1<=T<=100) which means the number of test cases.
Then T lines follow, each line starts with two integers N , K(1<=N<=100000 , 1<=K<=N), then N integers followed(all the integers are between -1000 and 1000).
Then T lines follow, each line starts with two integers N , K(1<=N<=100000 , 1<=K<=N), then N integers followed(all the integers are between -1000 and 1000).
Output
For each test case, you should output a line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the minimum start position, if still more than one , output the minimum length of them.
Sample Input
4
6 3
6 -1 2 -6 5 -5
6 4
6 -1 2 -6 5 -5
6 3
-1 2 -6 5 -5 6
6 6
-1 -1 -1 -1 -1 -1
Sample Output
7 1 3
7 1 3
7 6 2
-1 1 1
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 100010
#define INF 1<<31-1;
int a[2*N], sum[2*N];
int num[2*N];
int main(){
int n, k;
int beg, end;
int i, j, h, t;
int maxn;
int cnt;
scanf("%d", &cnt);
while(cnt --){
scanf("%d %d", &n, &k);
sum[0] = 0;
for(i = 1; i <= n; i ++){
scanf("%d", &a[i]);
sum[i] = sum[i-1] + a[i];
}
for(i = n+1; i <= 2*n; i ++){
sum[i] = sum[i-1] + a[i-n]; //因为是循环的数组,所以要拓展一下
}
maxn = -INF;
beg = 0; end = 0;
h = 0;
t = 0;
for(i = 0; i < n + k; i ++){
while(h < t && sum[num[t-1]] > sum[i])
t--;
num[t++] = i;//这样的用处是保证sum[num[i]]是单调递增的,则它都是能取到的最小的sum,所以每次能保证sum[i+1]-sum[num[头]]能得到最大的值
while(h < t && i+1 - num[h] > k)
h ++;//长度超过m,则头结点要后移
if(sum[i+1] - sum[num[h]] > maxn){
maxn = sum[i+1] - sum[num[h]];//更新maxs值和开始点结束点
beg = num[h] + 1;
end = i + 1;
}
}
if(beg > n)
beg -= n;
if(end > n)
end -= n;
cout << maxn << " " << beg << " " << end << endl;
}
return 0;
}
本文介绍了一种解决最大K子序列求和问题的方法,该问题涉及到在一个循环数组中找到长度不超过K的最大连续子序列的和及其起始和结束位置。文章通过具体的输入输出示例解释了算法的工作原理。
274

被折叠的 条评论
为什么被折叠?



