zoukankan      html  css  js  c++  java
  • 【bzoj3156】 防御准备

    http://www.lydsy.com/JudgeOnline/problem.php?id=3156 (题目链接)

    题意

      给出n个防御节点,每个节点有两种选择,可以花费a[i]建立一个防御塔,或者放置一个木偶,木偶的花费为到右端第一个防御塔的距离。求最少花费。

    Solution

      容易写出dp方程:$${f[i]=Min(f[j]+frac{(i-j)*(i-j-1)}{2})}$$

      其中${f[i]}$表示在${i}$处放置防御塔,前${i}$个节点已经完成防御所需要的最少花费。

      易证决策单调性,划出斜率式:$${i>=frac{(2*f[j]+j+j*j)-(2*f[k]+k+k*k)}{2*(j-k)}}$$

      其中${j<k<i}$。

    细节

      斜率里面${j*j}$以及${k*k}$记得开long long,用一个错的程序拍了好久→_→。。

    代码

    // bzoj3156
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define MOD 100000000
    #define inf 2147483640
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=1000010;
    LL a[maxn],q[maxn],n;
    LL f[maxn];
    
    double slope(LL j,LL k) {
    	return ((2.0*f[j]+j+j*j)-(2.0*f[k]+k+k*k))/(2.0*(j-k));
    }
    int main() {
    	scanf("%lld",&n);
    	for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
    	int l=1,r=1;q[1]=0;
    	for (int i=1;i<=n;i++) {
    		while (l<r && i>=slope(q[l],q[l+1])) l++;
    		f[i]=f[q[l]]+(i-q[l])*(i-q[l]-1)/2+a[i];
    		while (l<r && slope(q[r-1],q[r])>slope(q[r],i)) r--;
    		q[++r]=i;
    	}
    	//for (int i=1;i<=n;i++) printf("%d : %lld
    ",i,f[i]);
    	printf("%lld",f[n]);
    	return 0;
    }
    

      

  • 相关阅读:
    xampp 安装后无法启动apache 的解决方法
    前端常用规范
    FontAwesome 奥森图标的学习
    获取iframe 内元素的方法
    CSS中的选择器
    使用JavaScript缓存图片
    控制台console对象常用的一些方法
    清除浮动的方法
    浏览器存储:cookie
    HTML的文档类型:<!DOCTYPE >
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6005994.html
Copyright © 2011-2022 走看看