关于斜率优化的一些注意点
如果手写双端队列的话,把tail初值赋为0,因为判的是队列中元素个数是否大于等于2个因为,只有队中元素个数大于两个才会有斜率。
不要为了省事在推柿子是把数组下表的+1,-1去掉。
把柿子除过去时要看它是不是负的,如果是负的不等式变号。小学没学好.jpg
判斜率时尽量用乘法,因为分母可能出零,并且乘的的时候是大于等于或小于等于。
考场上要稍微yy一下,画一下直线,准确率会更高。
感觉过去学的太水了,全都忘光了,这么sb的斜率优化都调了这么长时间。
放个板子:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 double dp[N][22],a[N]; 5 int q[N][22]; 6 double cal(int k,int j,int h){//k<j k worse than j 7 return (dp[k][h]-dp[j][h]+a[k+1]*a[k+1]-a[j+1]*a[j+1])/(2.0*(a[k+1]-a[j+1])); 8 } 9 int main(){ 10 int n,k; 11 scanf("%d%d",&n,&k); 12 for(int i=1;i<=n;++i) scanf("%lf",&a[i]); 13 sort(a+1,a+n+1); 14 n=unique(a+1,a+n+1)-a-1; 15 dp[0][0]=0; 16 for(int i=1;i<=n;++i) dp[i][1]=(a[i]-a[1])*(a[i]-a[1]); 17 for(int j=2;j<=k;++j){ 18 int head=1,tail=0; 19 for(int i=1;i<=n;++i){ 20 while(head<tail&&cal(q[head][j-1],q[head+1][j-1],j-1)<=a[i]) ++head; 21 dp[i][j]=dp[q[head][j-1]][j-1]+(a[q[head][j-1]+1]-a[i])*(a[q[head][j-1]+1]-a[i]); 22 while(head<tail&&cal(q[tail-1][j-1],q[tail][j-1],j-1)>=cal(q[tail][j-1],i,j-1)) tail--; 23 q[++tail][j-1]=i; 24 // cout<<dp[i][j]<<" "; 25 } 26 // cout<<head<<" "<<tail<<endl; 27 // cout<<endl; 28 } 29 /*for(int i=1;i<=n;++i){ 30 for(int j=1;j<=k;++j) cout<<dp[i][j]<<" "; 31 cout<<endl; 32 }*/ 33 printf("%.2lf",dp[n][k]); 34 }