码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3709 K-Anonymous Sequence 斜率优化

时间:2014-10-21 01:08:17      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:blog   http   io   os   ar   使用   for   sp   2014   

容易得出简单的递推方程如下


f[i] = min{f[j] + sum[i] - sum[j] - (i-j) *x[j+1]   }

然后发现复杂度太高

这时可以看出是一个比较经典的斜率优化


f[i] =   min{f[j] +j *x[j+1] -sum[j] -i *x[j+1]}  +sum[i]

按照http://blog.csdn.net/sdj222555/article/details/8229192 中使用的斜率优化方法推导就行了

可以发现一些单调性是比较重要的

最后需要注意的由于有k这个条件的限制

所以某个决策点要入队的时候,需要延迟入队。

就是说走完 i 这个点的时候,把下一个点即(i+1)可能用到的状态加入队列,就是i-k+1

如代码所示


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#define INF 1011111111
#define eps 1e-12
#define MAXN 555555
#define MAXM 55555
using namespace std;
int n, k;
long long f[MAXN], x[MAXN], sum[MAXN];
int q[MAXN];
long long g(int j) {
    return f[j] + (long long)j * x[j] - sum[j];
}
int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &k);
        for(int i = 0; i < n; i++) x[i] = in();
        sum[0] = 0;
        for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + x[i - 1];
        int l = 1, r = 1;
        q[1] = 0; f[0] = 0;
        for(int i = 1; i <= n; i++) {
            while(q[l] + 2 * k <= i) l++;
            while(l < r && (long long)i * (x[q[l + 1]] - x[q[l]]) >= g(q[l + 1]) - g(q[l])) l++;
            f[i] = f[q[l]] + x[q[l]] * (long long)(q[l] - i) + sum[i] - sum[q[l]];
            if(i - k + 1 >= k) {
                while(l < r && (g(q[r]) - g(q[r - 1])) * (x[i - k + 1] - x[q[r]]) >= ((g(i - k + 1) - g(q[r])) * (x[q[r]] - x[q[r - 1]]))) r--;
                q[++r] = i - k + 1;
            }
        }
        printf("%I64d\n", f[n]);
    }
    return 0;
}


POJ 3709 K-Anonymous Sequence 斜率优化

标签:blog   http   io   os   ar   使用   for   sp   2014   

原文地址:http://blog.csdn.net/sdj222555/article/details/40324649

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!