• BZOJ1010「HNOI2008」题解


    Link

    Description

    (n) 件物品,第 (i) 件的长度为 (c_i).

    要把这个物品序列划分成 (k) 个仅端点相交的子串,如果把区间 ([l,r]) 划分为一个子串,那么这个子串的长度为 (x = r - l + sum_{i=l}^r c_i).

    这个子串的代价为 ((x - L)^2), 其中 (L) 是给定常数,求一种划分方案使得所有子串代价和最小。 (n leq 5 imes 10^4)

    Solution

    斜率优化板子。

    考虑朴素的 (mathbf{DP}), 设 (mathbf{DP}_i) 表示考虑了前 (i) 件物品时的答案,那么枚举上一个决策点,可以推出转移:

    [mathbf{DP}_i = min_{1 leq j < i} left { mathbf{DP}_{j} + left( sum_{k=j+1}^i c_k + i - j - 1 + L ight)^2 ight } ]

    用前缀和代替一下式子里面的 (Sigma), 再设 (f_i = sum_i + i) 简化一下.

    [mathbf{DP}_i = min_{1 leq j < i} left { mathbf{DP}_{j} + left(f_i - f_j - 1 - L ight)^2 ight } ]

    显然暴力 (mathbf{DP})(Theta(n^2)) 的,发现这个式子很符合斜率优化的运用条件,那么直接推式子。

    考虑设 (j_1, j_2) 是位置 (i) 的两个决策点,且满足 (j_2) 优于 (j_1), 那么显然有

    [mathbf{DP}_{j_1} + left( f_i - f_{j_1} - 1 - L ight)^2 geq mathbf{DP}_{j_2} + left( f_i - f_{j_2} - 1 - L ight)^2 ]

    把平方拆开,然后稍微合并一下同类项得:

    [2f_i(f_{j_2} + 1 + L) - 2f_i(f_{j_1} + 1 + L) geq mathbf{DP}_{j_2} - mathbf{DP}_{j_1} + left( f_{j_2} + 1 + L ight)^2 - left( f_{j_1} + 1 + L ight)^2 ]

    (g_i = (f_i + L + 1) ^ 2), 那么原式即

    [2f_i geq frac {mathbf{DP}_{j_2} - mathbf{DP}_{j_1} + g_{j_2} - g_{j_1}}{f_{j_2} - f_{j_1}} ]

    也就是说,如果满足上面那个不等式,我们可以得出决策 (j_2) 优于 (j_1).

    斜率优化是说把这个转移方程式写成 (y = kx+b) 的形式, 那么自然可以令 (mathbf {DP}_i + g_i = y, f_i = x), 那么上面不等式的右面就是一个 (frac {Delta y}{Delta x}) 的一次函数斜率形式,当两个决策点之间的连线斜率 (k leq 2f_i) 时满足决策点 (j_2) 优于决策点 (j_1).

    显然所有决策点之间构成了一个下凸壳, 那么直接单调队列算一下即可。

    Code

    /* Headers */
    #include <unordered_map>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <climits>
    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <set>
    #define FOR(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define ROF(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define FORL(i,a,b,c) for(long long i=(a);i<=(b);i+=(c))
    #define ROFL(i,a,b,c) for(long long i=(a);i>=(b);i-=(c))
    #define FORR(i,a,b,c) for(register int i=(a);i<=(b);i+=(c))
    #define ROFR(i,a,b,c) for(register int i=(a);i>=(b);i-=(c))
    #define RevEdge(x) x^1
    #define lowbit(x) x&(-x)
    #define LeftChild(x) x<<1
    #define RightChild(x) (x<<1)+1
    #define CLOSE_IN() fclose(stdin);
    #define CLOSE_OUT() fclose(stdout);
    #define FILE_IN(x) freopen(x,"r",stdin);
    #define FILE_OUT(x) freopen(x,"w",stdout);
    #define IOS(x) std::ios::sync_with_stdio(x)
    #define Dividing() printf("-----------------------------------
    ");
    namespace FastIO {
    #define gc() (iS == iT ? (iT = (iS = ibuff) + fread(ibuff, 1, SIZ, stdin), (iS == iT ? EOF : *iS++)) : *iS++)
        const int SIZ = 1 << 21 | 1;
        char* iS, * iT, ibuff[SIZ], obuff[SIZ], * oS = obuff, * oT = oS + SIZ - 1, fu[110], cc;
        int fr;
        inline void out() {
            fwrite(obuff, 1, oS - obuff, stdout);
            oS = obuff;
        }
        template<class Type>
        inline void read(Type& x) {
            x = 0;
            Type y = 1;
            for (cc = gc(); (cc > '9' || cc < '0') && cc != '-'; cc = gc());
            cc == '-' ? y = -1 : x = (cc & 15);
            for (cc = gc(); cc >= '0' && cc <= '9'; cc = gc())
                x = x * 10 + (cc & 15);
            x *= y;
        }
        template<class Type>
        inline void print(Type x, char text = '
    ') {
            if (x < 0)
                * oS++ = '-', x *= -1;
            if (x == 0)
                * oS++ = '0';
            while (x)
                fu[++fr] = x % 10 + '0', x /= 10;
            while (fr);
                * oS++ = fu[fr--];
            * oS++ = text;
            out();
        }
        inline void prints(char x[], char text = '
    ') {
            for (register int i = 0; x[i]; ++i)
                * oS++ = x[i];
            * oS++ = text;
            out();
        }
    }
    using namespace FastIO;
    using std::pow;
    template<typename T>
    inline T max(T a, T b) {return (a > b) ? a : b;}
    template<typename T>
    inline T min(T a, T b) {return (a > b) ? b : a;}
    /* definitions */
    #define int long long
    const int MAXN = 5e4 + 10;
    int n, L, c[MAXN], sum[MAXN], f[MAXN], g[MAXN], dp[MAXN];
    int q[MAXN], head, tail;
    /* functions */
    inline double slope(int x, int y) {
    	return (double) (dp[y] + g[y] - dp[x] - g[x]) / (f[y] - f[x]);
    }
    #undef int
    int main(int argc, char *argv[]) {
    	//FILE_IN("data.in");
    	read(n); read(L);
    	FOR(i, 1, n, 1) {
    		read(c[i]); sum[i] = sum[i - 1] + c[i];
    		f[i] = sum[i] + i; g[i] = (f[i] + L + 1) * (f[i] + L + 1);
    	} g[0] = (L + 1) * (L + 1);
    	FOR(i, 1, n, 1) {
    		while(head < tail && slope(q[head], q[head + 1]) <= (f[i] << 1)) head++;
    		dp[i] = dp[q[head]] + (f[i] - f[q[head]] - L - 1) * (f[i] - f[q[head]] - L - 1);
    		while(head < tail && slope(q[tail], i) < slope(q[tail - 1], q[tail])) tail--; q[++tail] = i;
    	} printf("%lld
    ", dp[n]);
    	return 0;
    }
    
  • 相关阅读:
    spark的环境安装
    (7)zabbix资产清单inventory管理
    (6)zabbix主机与组配置
    (5)zabbix配置详解
    (4)zabbix监控第一台服务器
    (3)zabbix用户管理
    (2)zabbix硬件需求
    (1) zabbix进程构成
    centos7系统root无法通过su切换到某个普通用户
    01基础复习
  • 原文地址:https://www.cnblogs.com/herself32-lyoi/p/13799485.html
Copyright © 2020-2023  润新知