bzoj3437 小P的牧场

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

题目大意(自己去看吧↑,我懒了~

这道题的题意跟防御准备有点像的嗯。

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

题解:

斜率优化

这个我自己搞不出方程QvQ好菜啊!于是我去问HYC大学霸怎么处理了嘿嘿嘿..

设sum[i]为前缀和,sm[i]为b[i]*(n-i)的后缀和,就是b[i]*(n-i)就表示该点放养量*这个点到末尾的距离呸牧场数目。[讲真。。起名无能sm就sm嘛= =]

f[i]表示在i建个控制站并搞完前i个牧场的最小花费

弄个sm之后我就会写方程啦~啦啦啦(- -

f[i]=f[j]+sm[j+1]-sm[i]-(sum[i-1]-sum[j])*(n-i)+a[i];

于是发现我自己好zz,如果不理解就画一下?啊很好理解的是吧~

-(n-i)*sum[j]+f[i]=f[j]+sm[j+1]-sm[i]-sum[i-1]*(n-i)+a[i];

日常化成截距式啦然后就好了。注意一下longlong咯

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
#define maxn 1010000

int q[maxn];
LL sum[maxn],sm[maxn],f[maxn],a[maxn],b[maxn];
double X(int j){return sum[j];}
double Y(int j){return f[j]+sm[j+1];}
double slop(int j1,int j2){return (Y(j2)-Y(j1))/(X(j2)-X(j1));}
int main()
{
	int n,i,l,r;
	scanf("%d",&n);sum[0]=0;
	memset(f,0,sizeof(f));
	for (i=1;i<=n;i++) scanf("%lld",&a[i]);
	for (i=1;i<=n;i++)
	{
		scanf("%lld",&b[i]);
		sum[i]=sum[i-1]+b[i];
	}sm[n]=0;
	for (i=n-1;i>=1;i--) sm[i]+=sm[i+1]+b[i]*(n-i);
	l=1;r=1;q[1]=0;
	for (i=1;i<=n;i++)
	{
		while (l<r && slop(q[l],q[l+1])<i-n) l++;
		int j=q[l];
		f[i]=f[j]+sm[j+1]-sm[i]-(sum[i-1]-sum[j])*(n-i)+a[i];
		while (l<r && slop(q[r-1],q[r])>slop(q[r],i)) r--;
		q[++r]=i;
	}printf("%lld",f[n]);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值