标签:name clu using || href type http i++ article
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3507
设 f[i],则 f[i] = f[j] + (s[i]-s[j])*(s[i]-s[j]) + m
即 f[j] + s[j]*s[j] = 2*s[i]*s[j] + f[i] - s[i]*s[i] - m
于是维护下凸包即可;
写成 double 的 slp 总是不对,把分母乘到对面就对了...
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define db double using namespace std; typedef long long ll; int const xn=5e5+5; int n,m,q[xn]; ll f[xn],s[xn]; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=0; ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘)ret=(ret<<3)+(ret<<1)+ch-‘0‘,ch=getchar(); return f?ret:-ret; } ll y(int i){return (ll)s[i]*s[i]+f[i];} ll up(int i,int j){return y(i)-y(j);} ll dn(int i,int j){return s[i]-s[j];} db slp(int a,int b){return 1.0*(y(a)-y(b))/(s[a]-s[b]);} int main() { while(~scanf("%d%d",&n,&m)) { memset(f,0,sizeof f); for(int i=1;i<=n;i++)scanf("%lld",&s[i]),s[i]+=s[i-1]; int h=0,t=0; for(int i=1;i<=n;i++) { //while(h<t&&slp(q[h+1],q[h])<=2*s[i])h++;//<= while(h<t&&up(q[h+1],q[h])<=2*s[i]*dn(q[h+1],q[h]))h++;//顺序 f[i]=f[q[h]]+(ll)(s[i]-s[q[h]])*(s[i]-s[q[h]])+m; //while(h<t&&slp(q[t],q[t-1])>=slp(i,q[t-1]))t--;//>= while(h<t&&up(q[t],q[t-1])*dn(i,q[t-1])>=up(i,q[t-1])*dn(q[t],q[t-1]))t--; q[++t]=i; } printf("%lld\n",f[n]); } return 0; }
hdu 3507 Print Article —— 斜率优化DP
标签:name clu using || href type http i++ article
原文地址:https://www.cnblogs.com/Zinn/p/9922497.html