HDOJ 3415 Max Sum of Max-K-sub-sequence(线段树优化DP)

来源:互联网 发布:js date format 函数 编辑:程序博客网 时间:2024/06/06 00:03

题意

给出一个环,求连续的k个数字中连续和最大是是多少,子串的开始下标和结束坐标是多少。

思路

第一次做这题的时候是在学单调队列的时候,单调队列的做法戳这里
这里我是直接dp搞,dp[i]=sum[i]min(sum[j])ik<=j<i
显然直接做复杂度O(nk)是超时的,就用线段树维护一下min(sum[j])就行了。
我在找ansl的时候用lower_bound在sum里面找min(sum[j])的下标不知道为什么WA= =。。后来改成在外面遍历一遍[ansr - k + 1,ansr]才没有WA,然后TLE了。。。我刚开始是每做到一个数就update进去这个i,然后改成直接建树的时候就PushUp了不再update就过了。

代码

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;#define LL long long#define Lowbit(x) ((x)&(-x))#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1|1#define MP(a, b) make_pair(a, b)const int INF = 0x3f3f3f3f;const int MOD = 1000000007;const int maxn = 1e5 + 10;const double eps = 1e-8;const double PI = acos(-1.0);typedef pair<int, int> pii;int a[maxn*2], sum[maxn*2];int mmin[(maxn*2)<<2];inline void PushUp(int rt){    mmin[rt] = min(mmin[rt<<1], mmin[rt<<1|1]);}void build(int l, int r, int rt){    if (l == r)    {        mmin[rt] = sum[l];        return ;    }    int mid = (l + r) >> 1;    build(lson);    build(rson);    PushUp(rt);}inline void update(int pos, int val, int l, int r, int rt){    if (pos <= l && r <= pos)    {        mmin[rt] = val;        return ;    }    int mid = (l + r) >> 1;    if (pos <= mid) update(pos, val, lson);    if (pos > mid) update(pos, val, rson);    PushUp(rt);}inline int query(int L, int R, int l, int r, int rt){    if (L <= l && r <= R)    {        return mmin[rt];    }    int mid = (l + r) >> 1;    int res = INF;    if (L <= mid) res = min(res, query(L, R, lson));    if (R > mid) res = min(res, query(L, R, rson));    return res;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int n, k, T;    scanf("%d", &T);    while (T--){         //T是后加的所以格式丑了点= =    scanf("%d%d", &n, &k);    for (int i = 1; i <= n; i++)        scanf("%d", &a[i]), a[i+n] = a[i];    n <<= 1;    memset(sum, 0x3f, sizeof(sum));    memset(mmin, 0x3f, sizeof(mmin));    sum[0] = 0;    for (int i = 1; i <= n; i++)        sum[i] = sum[i-1] + a[i];    build(1, n, 1);    int ans = sum[1], ansl = 1, ansr = 1;    for (int i = 2; i <= n; i++)    {        if (i - k <= 0 && sum[i] - sum[0] > ans)        {            ans = sum[i] - sum[0];            ansl = 1;            ansr = i;        }        int l = max(i - k, 1), r = i - 1;        int minval = query(l, r, 1, n, 1);        //printf("%d %d %d %d\n", l, r+1, minval, sum[i] - minval);        if (sum[i] - minval > ans)        {            ans = sum[i] - minval;            ansr = i;        }    }    for (int i = max(ansr - k + 1, 1); i <= ansr; i++)        if (sum[ansr] - sum[i-1] == ans)        {            ansl = i;            break;        }    if (ansl % (n >> 1) == 0) ansl = (n >> 1);    else ansl %= (n >> 1);    if (ansr % (n >> 1) == 0) ansr = (n >> 1);    else ansr %= (n >> 1);    printf("%d %d %d\n", ans, ansl, ansr);}    return 0;}
0 0
原创粉丝点击