HDU 3415 Max Sum of Max-K-sub-sequence(长度不超过k的最大连续子序列和,单调队列)

来源:互联网 发布:淘宝退款卖家拒绝几次 编辑:程序博客网 时间:2024/05/22 00:29

题目链接:
HDU 3415 Max Sum of Max-K-sub-sequence
题意:
n个数,首尾相连,求长度不超过k的最大连续子序列和。
数据范围:1n100000,1kn
分析:
因为考虑首尾相连,所以我们把n个数看成2n个数,其中data[n+]=data[i]。求个前缀和sum[]。我们考虑以i为结尾的长度不超过k的最大连续子序列和。显然是sum[i]min(sum[j]),j[ik,i1].那么问题就转化为求区间最小值了,所以我们维护一个单调非递增队列即可。注意下边界。

#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;}
0 0
原创粉丝点击