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; }