HDU_3045

    这个题目如果一开始把各个值排序之后的话,就和POJ_3709那个题目基本一样了,只不过看discuss上说这个题目一开始读数据的时候就要用long long int。

    剩下的工作就是和POJ_3709一样了,用斜率优化+单调队列的dp去做。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXD 400010
long long int a[MAXD], f[MAXD], A[MAXD];
int N, K, q[MAXD];
int cmp(const void *_p, const void *_q)
{
long long int *p = (long long int *)_p, *q = (long long int *)_q;
return *p < *q ? -1 : 1;
}
void init()
{
int i, j, k;
for(i = 1; i <= N; i ++)
scanf("%lld", &a[i]);
qsort(a + 1, N, sizeof(a[0]), cmp);
A[0] = 0;
for(i = 1; i <= N; i ++)
A[i] = A[i - 1] + a[i];
}
long long int getf(int i)
{
return f[i] - A[i] + i * a[i + 1];
}
void solve()
{
int i, j, k, front, rear, x, y, z;
front = rear = 0;
q[rear ++] = 0;
f[0] = 0;
for(i = 1; i <= N; i ++)
{
while(front < rear - 1)
{
x = q[front], y = q[front + 1];
if(i * (a[y + 1] - a[x + 1]) < getf(y) - getf(x))
break;
front ++;
}
j = q[front];
f[i] = f[j] + A[i] - A[j] - (i - j) * a[j + 1];
if(i + 1 - K >= K)
{
q[rear] = i + 1 - K;
for(j = rear - 1; j > front; j --)
{
x = q[j - 1], y = q[j], z = q[j + 1];
if((a[z + 1] - a[y + 1]) * (getf(y) - getf(x)) < (a[y + 1] - a[x + 1]) * (getf(z) - getf(y)))
break;
q[rear = j] = q[j + 1];
}
++ rear;
}
}
printf("%I64d\n", f[N]);
}
int main()
{
while(scanf("%d%d", &N, &K) == 2)
{
init();
solve();
}
return 0;
}


posted on 2012-03-12 12:37  Staginner  阅读(373)  评论(0编辑  收藏  举报