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

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

    题目大意

    一条线上N个(检查)点,编号1~N,一个点j上可以建一个守卫塔花费为a[j],也可以选择放个木偶(为什么会是木偶= =),花费是这个点右边建的第一个守卫塔i到这个点的距离,即i-j。问最小花费。

    ==========================================

    题解

    斜率优化

    设sum[i]为前缀和.f[i]表示在i建塔并搞完了i之前的最小花费。

    因为最后那个一定要,所以答案就是f[n]。

    方程为f[i]=f[j]+a[i]+sigama(i-k), j+1≤k<i

    化一下得:f[i]=f[j]+a[i]+(i-j-1)*i-(sum[i-1]-sum[j]);

    拆项、转移:i*j+f[i]=f[j]+sum[j] +(a[i]+i^2-i-sum[i-1])常数部分忽略~


    吐槽

    因为把(i-j-1)*i转LL的时候多了个括号结果一直WA...还以为是自己哪里打错或者方程推错了= =..

    去看大神们的博客,,结果都跟我的方程不一样QWQ蒟蒻表示看不懂啊orz为什么要反过来..

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    #define maxn 1010000
    
    int q[maxn],l,r;
    LL f[maxn],sum[maxn],a[maxn];
    double Y(int j){return f[j]+sum[j];}
    double X(int j){return j;}
    double slop(int j1,int j2){return (Y(j2)-Y(j1))/(X(j2)-X(j1));}
    int main()
    {
    	int n,i;scanf("%d",&n);
    	sum[0]=0;
    	for (i=1;i<=n;i++)
    	{
    		scanf("%lld",&a[i]);
    		sum[i]=sum[i-1]+i;
    	}
    	memset(f,0,sizeof(f));
    	l=r=1;q[1]=0;
    	for (i=1;i<=n;i++)
    	{
    		while (l<r && slop(q[l],q[l+1])<i) l++;
    		int j=q[l];
    		f[i]=f[j]+a[i]+(LL)(i-j-1)*i-(sum[i-1]-sum[j]);
    		while (l<r && slop(q[r-1],q[r])>slop(q[r],i)) r--;
    		q[++r]=i;
    	}printf("%lld
    ",f[n]);
    	return 0;
    }


  • 相关阅读:
    继承与多态,Instanceof关键字
    面向对象,单例模式
    方法
    数组
    流程控制
    基础语法
    连接linux四大远程工具
    MYSQL-索引的设计
    银行一类(Ⅰ类)、二类(Ⅱ类)、三类(Ⅲ类)账户区别是什么?
    真正有效的学习
  • 原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527866.html
Copyright © 2011-2022 走看看