hdu2993 MAX Average Problem (斜率dp)

参考:http://www.cnblogs.com/kuangbin/archive/2012/08/27/2657878.html

//#pragma warning (disable: 4786)
//#pragma comment (linker, "/STACK:16777216")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RS(s) scanf("%s", s)

typedef long long LL;
const int INF = 1000000007;
const double eps = 1e-10;
const int MAXN = 500010;

int n, m;
int sum[MAXN];
int q[MAXN];

double Up(int k, int j)
{
    return sum[j] - sum[k];
}
double Down(int k, int j)
{
    return j - k;
}

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

//o(n)法
//double solve()
//{
//    int be, ed;
//    be = 1;
//    ed = 0;
//    double ans = 0;
//    double tmp = 0;
//
////    q[++ed] = 0;///
//    int j;
//    for (int i = m; i <= n; i++)
//    {
//        j = i - m;
//        while (be < ed && Up(q[ed - 1], q[ed]) * Down(q[ed], j) >= Up(q[ed], j) * Down(q[ed - 1], q[ed]))
//            ed--;
//        q[++ed] = j;
//
//        while (be < ed && getDp(i, q[be]) <= getDp(i, q[be + 1]))
//            be++;
//        j = q[be];
//        tmp = getDp(i, j);
//        ans = max(ans, tmp);
//    }
//    return ans;
//}

///o(n*log(n))法,不单调是可用此法
bool check(int mid, int i)
{
//    if (Up(q[mid], q[mid + 1]) * Down(q[mid + 1], i) >= Up(q[mid + 1], i) * Down(q[mid], q[mid + 1])) return 1;
    if (getDp(i, q[mid]) >= getDp(i, q[mid + 1])) return 1;
    return 0;
}

///注意写法
int SB(int i, int l, int r)///[l, r]
{
    int mid;
    while (l < r)///区间长度至少为2
    {
        mid = (l + r) >> 1;
        if (check(mid, i)) r = mid;///!!!要是mid
        else l = mid + 1;
    }
    return l;
}

double fun()
{
    int top = 1;
    int j;
    double ans = 0, tmp = 0;
    FE(i, m, n)
    {
        j = i - m;
        while (top > 1 && Up(q[top - 1], q[top]) * Down(q[top], j) >= Up(q[top], j) * Down(q[top - 1], q[top]))
            top--;
        q[++top] = j;

        j = q[SB(i, 1, top)];
        tmp = getDp(i, j);
        ans = max(ans, tmp);
    }
    return ans;
}

int getInt()
{
    int x = 0;
    char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9')
    {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x;
}

int main ()
{
    int x;
    while (~RII(n, m))
    {
        sum[0] = 0;
        FE(i, 1, n)
        {
            x = getInt();
            sum[i] = sum[i - 1] + x;
        }
        printf("%.2lf
", fun());
    }
    return 0;
}



原文地址:https://www.cnblogs.com/riskyer/p/3397847.html