关于斜率优化的一些注意点

如果手写双端队列的话,把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 }
View Code

 

posted @ 2019-10-26 16:39  Barça_10  阅读(260)  评论(0编辑  收藏  举报