日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

YBTOJ洛谷P3195:玩具装箱(斜率优化dp)

發布時間:2023/12/3 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 YBTOJ洛谷P3195:玩具装箱(斜率优化dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳送門

文章目錄

  • 前言
  • 解析
  • 代碼

前言

斜率優化dp,就是利用斜率優化的dp

(逃)

解析

第一道斜優的題
分析題目
sumisum_isumi?為1-i的c的前綴和
容易寫出dp轉移式:
dpi=min(dpj+(sumi?sumj+i?j?1?L)2)dp_i=min(dp_j+(sum_i-sum_j+i-j-1-L)^2)dpi?=min(dpj?+(sumi??sumj?+i?j?1?L)2)

但是平方轉移會T掉
考慮優化
設:
ai=sumi+ia_i=sum_i+iai?=sumi?+i
bi=sumi+i+1+Lb_i=sum_i+i+1+Lbi?=sumi?+i+1+L
注意到對于固定的 i,a和b都是可求的定值
那么上面的dp,就可以寫成:
dpi=min(dpj+(ai?bj)2)dp_i=min(dp_j+(a_i-b_j)^2)dpi?=min(dpj?+(ai??bj?)2)
把平方拆開:
dpi=min(dpj+ai2+bj2?2?ai?bj)dp_i=min(dp_j+a_i^2+b_j^2-2*a_i*b_j)dpi?=min(dpj?+ai2?+bj2??2?ai??bj?)
為了轉移優化,我們需要移一下項:
2?ai?bj+dpi?ai2=dpj+bj22*a_i*b_j+dp_i-a_i^2=dp_j+b_j^22?ai??bj?+dpi??ai2?=dpj?+bj2?

上面那個式子可以看成一個bjb_jbj?為未知數,斜率為2?ai2*a_i2?ai?,且經過(bj,dpj+bj2)(b_j,dp_j+b_j^2)(bj?,dpj?+bj2?)的一次函數
沒明白?這么看:
f(x)=2?ai?x+dpi?ai2f(x)=2*a_i*x+dp_i-a_i^2f(x)=2?ai??x+dpi??ai2?
f(bj)=dpj+bj2f(b_j)=dp_j+b_j^2f(bj?)=dpj?+bj2?
dpidp_idpi?就是這個函數與y軸的截距加上aia_iai?的平方,因此我們實際上就是要使函數在y軸上的截距最小
有了這個函數之后,我們就可以開始嘗試優化了

對于每一個新的要求的dp[i],其直線對應的斜率是固定的
我們維護一個可以作為轉移點的隊列,其中的決策點對應的點對(b[x],dp[x]+b[x]^2)形成一個凸包的結構

由于隨著 i 的增大,其直線的斜率(2?ai2*a_i2?ai?)單調遞增,所以位于凸包上方的點是一定不會作為最優決策點的
若記A、B兩點之間的斜率為slope(A、B)
不難看出,要使其這條直線的y軸截距最小,我們應該找到**第一個
slope(P[j],P[j+1])>2?aislope(P[j],P[j+1])>2*a~i~slopeP[j],P[j+1])>2?a?i? 的位置
而且由于斜率單調遞增,Pj左側的點以后一定不會再被選到了
所以我們可以用一個單調隊列來維護
時間復雜度降為O(n)

代碼

#include<bits/stdc++.h> #define I register int using namespace std; #define ll long long const int N=5e4+10; ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f; } int n; ll sum[N],c[N],a[N],b[N],l,dp[N]; struct pos{ll x,y;int pl; }; pos q[N]; int st,ed; double slope(pos u,pos v){return 1.0*(v.y-u.y)/(v.x-u.x); } int main(){ // freopen("a.in","r",stdin); // freopen("a.out","w",stdout);n=read();l=read();for(int i=1;i<=n;i++){//printf("ok i=%d\n",i);c[i]=read();sum[i]=sum[i-1]+c[i];a[i]=sum[i]+i;b[i]=sum[i]+i+l+1;}b[0]=l+1;st=ed=1;q[1]={b[0],b[0]*b[0],0};for(int i=1;i<=n;i++){ll k=2*a[i];while(st<ed&&slope(q[st],q[st+1])<k) st++;ll x=q[st].x,y=q[st].y;int pl=q[st].pl;dp[i]=y+a[i]*a[i]-2*a[i]*b[pl];//printf("i=%d st=%lld dp=%lld k=%lld\n ",i,q[st].pl,dp[i],k);//for(int i=st;i<=ed;i++) printf("%d:(%lld %lld %lld) ",i,q[i].x,q[i].y,q[i].pl);//printf("\n\n");pos now=(pos){b[i],dp[i]+b[i]*b[i],i};while(st<ed&&slope(q[ed-1],q[ed])>slope(q[ed-1],now)){ed--;// printf("ou2!\n");}q[++ed]=now;}printf("%lld",(long long)dp[n]);return 0; } /* 6 10 5 8 5 10 19 1 */

總結

以上是生活随笔為你收集整理的YBTOJ洛谷P3195:玩具装箱(斜率优化dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。