zoukankan      html  css  js  c++  java
  • [CEOI2017] Building Bridges

    ( ext{Solution})
    很容易想到 (dp)

    [f_i = f_j + (h_i-h_j)^2 + sum_{k=i+1}^{j-1}w_k ]

    (s_i = sum_{k=1}^i w_i)

    [f_i = s_{i-1} + h_i^2 -2h_j imes h_i + f_j + h_j^2 - s_j ]

    显然可以把决策 (j) 看成斜率为 (-2h_j) 截距为 (f_j + h_j^2 - s_j) 的直线
    然后求 (x = h_i) 的最小值
    李超线段树优化即可,(O(n log n))

    当然这种 (dp) 看到平方项立刻就会想用斜率优化
    维护下凸包,发现需要用平衡树维护,或者用 (CDQ) 分治处理
    这题就成了眼切的题了

    李超线段树做法

    ( ext{Code})

    #include <cstdio>
    #include <iostream>
    #define ls (p << 1)
    #define rs (ls | 1)
    #define re register
    using namespace std;
    typedef long long LL;
    
    const int N = 1000010;
    int n, len, h[N], w[N], fl[N << 2]; LL f[N], s[N];
    struct line{LL k , b;}seg[N << 2];
    inline double Isc(LL k1, LL b1, LL k2, LL b2){return 1.0 * (b2 - b1) / (k1 - k2);}
    
    void update(int p, int l, int r, LL k, LL b)
    {
    	if (!fl[p]){seg[p] = line{k, b}, fl[p] = 1; return;}
    	LL f1 = seg[p].k * l + seg[p].b, f2 = seg[p].k * r + seg[p].b, f3 = k * l + b , f4 = k * r + b;
    	if (f3 >= f1 && f4 >= f2) return;
    	else if (f3 <= f1 && f4 <= f2) return void(seg[p] = line{k, b});
    	int mid = (l + r) >> 1; double len = Isc(k, b, seg[p].k, seg[p].b);
    	if (f3 <= f1)
    	{
    		if (len <= mid) update(ls, l, mid, k, b);
    		else update(rs, mid + 1, r, seg[p].k, seg[p].b), seg[p] = line{k, b};
    	}
    	else{
    		if (len > mid) update(rs, mid + 1, r, k, b);
    		else update(ls, l, mid, seg[p].k, seg[p].b), seg[p] = line{k, b};
    	}
    }
    LL query(int p, int l, int r, int x)
    {
    	LL ans = seg[p].k * x + seg[p].b;
    	if (l == r) return ans;	
    	int mid = (l + r) >> 1;
    	if (x <= mid) ans = min(ans , query(ls, l, mid, x));
    	else ans = min(ans , query(rs, mid + 1, r, x));
    	return ans;
    }
    
    int main()
    {
    	scanf("%d", &n);
    	for(re int i = 1; i <= n; i++) scanf("%d", &h[i]), len = max(h[i], len);
    	for(re int i = 1; i <= n; i++) scanf("%d", &w[i]), s[i] = s[i - 1] + w[i];
    	for(re int i = 1; i <= 4000001; i++) seg[i].b = 1e18 , seg[i].k = 0;
    	update(1, 0, len, -2LL * h[1], 1LL * h[1] * h[1] - s[1]);
    	for(re int i = 2; i <= n; i++)
    	{
    		f[i] = s[i - 1] + 1LL * h[i] * h[i] + query(1, 0, len, h[i]);
    		if (i ^ n) update(1, 0, len, -2LL * h[i], f[i] + 1LL * h[i] * h[i] - s[i]);
    	}
    	printf("%lld
    ", f[n]);
    }
    
  • 相关阅读:
    使用NDK编译 libyuv <转>
    x264中重要结构体参数解释,参数设置,函数说明 <转>
    x264的一些参数设置对编码效率的影响
    首都儿研所开钙片!!!
    Android 媒体编解码器(转)
    opengl版本和扩展
    ffmpeg一揽子
    Android 使用SWIG生成Jni代码<转>
    CF 19D 线段树+set压缩坐标轴+离散化map
    android4.0 FaceDetection笔记
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15512829.html
Copyright © 2011-2022 走看看