题目链接:
HDU 3415 Max Sum of Max-K-sub-sequence
题意:
给
n
个数,首尾相连,求长度不超过
数据范围:
1≤n≤100000,1≤k≤n
分析:
因为考虑首尾相连,所以我们把
n
个数看成
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <climits>
using namespace std;
typedef long long ll;
const int MAX_N = 100010 * 2;
int T, n, k, head, tail, st, ed;
ll data[MAX_N], sum[MAX_N];
int que[MAX_N];
int main()
{
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &k);
sum[0] = 0;
for (int i = 1; i <= n; ++i) {
scanf("%lld", &data[i]);
data[i + n] = data[i];
}
ll ans = data[1], tmp;
st = 1, ed = 1;
for (int i = 1; i <= 2 * n; ++i) {
sum[i] = sum[i - 1] + data[i];
if (i <= k) {
if (sum[i] > ans) {
ans = sum[i], ed = i;
}
}
}
// 维护单调递增队列,存前缀和
head = tail = 0;
que[tail++] = 1;
for (int i = 2; i <= n + k; ++i) {
// 剔除在i之前距离超过k的前缀和
while (head != tail && i - que[head] > k) {
++head;
}
// 剔除在i之前前缀和大的前缀和
while (head != tail && sum[i] <= sum[que[tail - 1]]) {
--tail;
}
int flag = -1;
if (i <= k && sum[que[head]] >= 0) {
tmp = sum[i], flag = 1;
} else if (head == tail) {
tmp = data[i], flag = 2;
} else {
tmp = sum[i] - sum[que[head]];
flag = 3;
}
if (tmp > ans) {
ans = tmp;
if (flag == 1) st = 1;
else if (flag == 2) st = i;
else st = que[head] + 1;
ed = i;
}
que[tail++] = i;
//printf("i = %d ans = %d:\n", i, ans);
/*
for (int j = head; j < tail; ++j) {
printf("%d ", sum[que[j]]);
}
printf("\n");
*/
}
if (st > n) st -= n;
if (ed > n) ed -= n;
printf("%lld %d %d\n", ans, st, ed);
}
return 0;
}