博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[hdu][3045][Picnic Cows]

Posted on 2012-05-12 15:53  紫华弦筝  阅读(142)  评论(0编辑  收藏  举报

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3045

View Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>

#define ll __int64
#define clr(a,b) memset(a, b, sizeof(a))
using namespace std;

const int N = 500000+10;
const int M = 10000+10;
const int inf = 0x3f3f3f3f;

int m, n, l, r;
int q[N];
ll a[N], s[N], dp[N];

// dp[i] = min{dp[j]+sum[i]-sum[j]-(i-j)*a[j+1]}

void input()
{
    for (int i=1; i<=n; i++)
        scanf("%I64d", &a[i]);
    sort(a+1, a+n+1);
    a[0] = s[0] = dp[0] = 0;
    for (int i=1; i<=n; i++)
        s[i] = s[i-1] + a[i], dp[i] = 0;
}

bool super1(int k1, int k2, int k3, int i)
{
    return (dp[k3]-dp[k2]-(i-k3)*a[k3+1]+(i-k2)*a[k2+1])*(s[k2]-s[k1])
           <=(dp[k2]-dp[k1]-(i-k2)*a[k2+1]+(i-k1)*a[k1+1])*(s[k3]-s[k2]); // =很重要,,poj3709上没有这个WA了
}

bool super2(int k1, int k2, int i)
{
    return dp[k1]-s[k1]-(i-k1)*a[k1+1]>=dp[k2]-s[k2]-(i-k2)*a[k2+1];
}

int main()
{
    //freopen("D:/a.txt", "r", stdin);
    while (~scanf("%d%d", &n, &m))
    {

        input();
        q[l=0] = 0, r=-1;
        for (int i=1; i<=n; i++)
        {
            if (i>=2*m)
            {
                int now = i-m;
                while (l<r && super1(q[r-1],q[r],now,i))r--;
                q[++r]=now;
            }
            while (l<r && super2(q[l],q[l+1],i))l++;
            int k = q[l];
            dp[i] = dp[k]+s[i]-s[k]-(i-k)*(a[k+1]);
        }
        printf("%I64d\n", dp[n]);
    }
    return 0;
}