HDU MAX Average Problem(斜率优化DP)

这个也是论文上的例题,给你一个正数序列,注意全是正数,否则就不满足和的单调性了,关于这个结论某些部分就不能在运用了,我先说一下前提条件,我就是前提条件没搞请,才弄的模模糊糊的,弄清楚前提条件后就会发现其实不是很难的。

前提条件:

1.所有的数均是(保证了他们的和是单调递增的)

2.求的是连续的序列,且序列的长度大于等于k

3.求的是序列的最大平均值,也就是(i, sum[i])值中斜率最大的那个值

解体思路:

现在我只是干讲,如果感觉不形象的话,可以参考那篇著名的论文。

由于我们是要求斜率最大值,如果枚举的话,我们肯定是把当前的点与它前面的所有的点求斜率,取最大值。

现在我们想降低复杂度,我们可以从两个方面入手,

1,去掉每个位置前面的那些在后来的枚举中不可能产生最优解的点

2,快速的去定位最优解

首先讲第一个:

1.如何减少不必要的枚举呢?

我们假设存在三个点,i,j, k三个点构成的是上凸包,现在我们沿着j,k作延长线,如何后来的点在延长线的下方,那么该后来的点是不能构成最优解的,因为当前延长线的解已经比后来的点构成的所有的点优或则说与i构成的直线的斜率一定比与j构成的斜率大,如果后来的点在延长线的上方,那么你会发现与k构成的斜率肯定比与j构成的斜率大,那么问题就出现了,j不可能在后来的更新中形成最优解,那么就可以将其删除,这样在后来的枚举中少了它了。很神奇的证明,不过的确特别的有用。

2.如何更快的去定位最优解呢?

一般的做法就是二分,不过这里的做法很绝,把原来O(NlgN)的做法优化到了,O(N)

还是把不可能构成最优解的删掉,(注意sum[i]是单调递增的),如果当前构不成最优解,那么在后来的点着中是不可能构成最优解的,因此可以删掉,到底为什么,还是自己看自己想。这里维持最小长度为k还是很巧秒的,不过HDU交C++可过,交G++TLE,据说只要有C++那么它的服务器系统肯定是windows,那么交G++调用MingW肯定会慢的。

代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 100010;
double sum[MAXN];
int que[MAXN];
int front, tail;

double get_k(int i, int j) {
    return (sum[i] - sum[j]) / (i - j);
}

int main() {
    int n, k;
    while (scanf("%d%d", &n, &k) == 2) {
        int temp;
        sum[0] = 0;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &temp);
            sum[i] = sum[i - 1] + temp;
        }
        front = 0, tail = -1;
        double ans = 0;
        for (int i = k; i <= n; i++) {
            int now = i - k;
            while (front < tail && get_k(que[tail], que[tail - 1]) > get_k(que[tail], now)) tail--;
            que[++tail] = now;
            while (front < tail && get_k(que[front], que[front + 1]) < get_k(que[front + 1], i)) front++;
            ans = max(ans, get_k(que[front], i));
        }
        printf("%.2lf\n", ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值