Maximum Absurdity

codeforces B.Maximum Absurdity 解题报告
题目链接:http://codeforces.com/contest/332/problem/B

题意:在一个序列中,在所有长度为k的区间里找出两个不重叠的最大和,输出这两个最大和所对应的开头的位置a和b。

 一开始没有想到用dp来做,于是有了以下的错误思路(读者可以忽略):声明一个结构体,包括head(保存起始点)、tail(保存结束点)还有sum(保存长度为k的区间的和)。计算出整个序列所有k个小区间的和sum,按sum从大到小排序(隐含的弊端:排序会导致区间与区间之间起始点和结束点的位置很不确定)由于a、b不能相交,所以当找到没有重叠的部分,就找到当前最优解,但不一定是整个题目的最优解。还要比较各个序列的最优解,以便找到整个题目的最优解,但是重叠的判断会有很多种情况(sum的排序导致的),于是参考了别人的代码......

 正确的思路:当然就是用dp做啦。而且,也是需要计算出所有长度为k的区间的和,按顺序保存在数组b[]中(比我的方法好多啦)。接下来是找出状态转移方程:  max{b[i]} + b[i+k]。另外,考虑到数据比较大,所以用长整型(_int 64)来保存数据。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

#define LL __int64
const int maxn = 200000 + 10;
LL a[maxn], b[maxn];

int main()
{
    int i, j, n, k;
    LL tl, maxt, maxl, maxr, ans;
    while (scanf("%d%d", &n, &k) != EOF)
    {
        LL temp = 0;
        for (i = 1; i <= n; i++)
        {
            scanf("%I64d", &temp);
            a[i] = a[i-1] + temp;       // a[i]保存的是从第1至第i个元素的总和 
        //  printf("a[%d] = %I64d\t", i, a[i]);
        }
        for (i = 0, j = 1; i <= n-k; i++, j++)
        {
            b[j] = a[i+k] - a[i];    // b[j]保存的是所有长度为k的区间的总和
        //  printf("b[%d] = %I64d\t", j, b[j]);
        }
        maxt = ans = b[1];
        tl = maxl = maxr = 1;           // maxl: a   maxr:b
        for (i = 1; i+k <= n-k+1; i++)   // 循环的判别要注意,要保证取值不能越界
        {
            if (b[i] > ans)            // 状态转移方程中的max{b[i]},用ans保存
            {
                ans = b[i];
                tl = i;
        //      printf("ans = %I64d\n", ans);
            }
            if (b[i+k] + ans > maxt)
            {
                maxt= b[i+k] + ans;
                maxl = tl;
                maxr = i+k;
        //      printf("maxt = %I64d\n", maxt);
        //      printf("maxl = %I64d\tmaxr = %I64d\n", maxl, maxr);
            }
        }
        printf("%I64d %I64d\n", maxl, maxr);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值