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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[WF2011] MachineWorks(李超树优化dp)

發布時間:2023/12/3 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [WF2011] MachineWorks(李超树优化dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

[WF2011]MachineWorks

problem

BZOJ3963

solution

來得比較快的是,直接設 dpi,j:dp_{i,j}:dpi,j?: 考慮第 jjj 天換購 iii 機器。

但是馬上注意到天數是 1e91e91e9 級別的,而機器是 1e51e51e5 級別。

稍微想想,就能知道,因為每天機器只能在那一天買,而為了最大化利益,肯定不可能買了一臺機器在換購下一臺機器前就賣了。

所以真正有用的只有 nnn 天——離散化!!

因為機器過了那天就不能買了,所以將機器按照購買天數升序排序。

考慮 dpi:dp_i:dpi?: 當前以 iii 機器執行轉型期的已知利潤最大值。

有兩種情況:

  • case1:就是前面一臺機器都沒買,用最開始的錢購買這一臺機器開始賺錢,比較簡單。

  • case2:考慮在換購這一臺機器前是用的機器 jjj

    則有轉移:dpi=max?{dpj+Gj(Di?Dj?1)+Rj?Pi}dp_i=\max\Big\{dp_j+G_j\Big(D_i-D_j-1\Big)+R_j-P_i\Big\}dpi?=max{dpj?+Gj?(Di??Dj??1)+Rj??Pi?}

    整理一下得到,dpi=max?{?Gj?Di+dpj?Gj(Dj+1)+Rj}?Pidp_i=\max\Big\{-G_j·D_i+dp_j-G_j(D_j+1)+R_j\Big\}-P_idpi?=max{?Gj??Di?+dpj??Gj?(Dj?+1)+Rj?}?Pi?

然后要用 dpidp_idpi? 去更新最后的答案,dpidp_idpi? 是已知的利潤,最后的答案就是假設這個機器不再改變。

ans=max{dpi+(T?Di)G(i)+R(i)}ans=max\Big\{dp_i+(T-D_i)G(i)+R(i)\Big\}ans=max{dpi?+(T?Di?)G(i)+R(i)}

當然要滿足 前面賺的錢 / 最開始的錢 能夠買得起這件機器,再更新,否則會出錯。

比如這臺機器賺的利潤非常高,結果買不起,答案可能會被這臺壓根買不了的機器利潤更新成最大值。

dpidp_idpi? 的轉移式子簡直不能太熟悉了!

因為 GGG 不具有單調性,所以不能斜率優化。

就算能,李超樹不香嗎??只要不會超時,寧可死也要用李超不用斜率優化。

?Gj-G_j?Gj? 當成 kkkdpj?Gj(Dj+1)+Rjdp_j-G_j(D_j+1)+R_jdpj??Gj?(Dj?+1)+Rj? 當成 bbb,每次以 DiD_iDi? 查。

code

#include <bits/stdc++.h> using namespace std; #define maxn 100005 #define int long long int n, C, T; int d[maxn], f[maxn]; struct Node { int D, P, R, G; }v[maxn]; struct node { int k, b; }t[maxn << 2];#define lson now << 1 #define rson now << 1 | 1 #define mid ( ( l + r ) >> 1 )int calc( node l, int x ) { return l.k * d[x] + l.b; }bool cover( node Old, node New, int x ) {return calc( Old, x ) <= calc( New, x ); }void insert( int now, int l, int r, node New ) {if( cover( t[now], New, l ) and cover( t[now], New, r ) ) {t[now] = New;return;}if( l == r ) return;if( cover( t[now], New, mid ) ) swap( t[now], New );if( cover( t[now], New, l ) ) insert( lson, l, mid, New );if( cover( t[now], New, r ) ) insert( rson, mid + 1, r, New ); }int query( int now, int l, int r, int x ) {if( ! t[now].k and ! t[now].b ) return 0;if( l == r ) return calc( t[now], x );int ans;if( x <= mid ) ans = query( lson, l, mid, x );else ans = query( rson, mid + 1, r, x );return max( ans, calc( t[now], x ) ); }signed main() {int Case = 0;while( scanf( "%lld %lld %lld", &n, &C, &T ) ) {if( ! n and ! C and ! T ) break;memset( t, 0, sizeof( t ) );memset( f, 0, sizeof( f ) );int ans = C;for( int i = 1, D, P, R, G;i <= n;i ++ ) {scanf( "%lld %lld %lld %lld", &D, &P, &R, &G );v[i] = { D, P, R, G };d[i] = D;}sort( d + 1, d + n + 1 );sort( v + 1, v + n + 1, []( Node x, Node y ) { return x.D < y.D; } );int m = unique( d + 1, d + n + 1 ) - d - 1;for( int i = 1;i <= n;i ++ ) v[i].D = lower_bound( d + 1, d + m + 1, v[i].D ) - d;for( int i = 1;i <= n;i ++ ) {int x = max( query( 1, 1, m, v[i].D ), C );if( x >= v[i].P ) {f[i] = x - v[i].P + v[i].R;ans = max( ans, f[i] + v[i].G * ( T - d[v[i].D] ) );insert( 1, 1, m, { v[i].G, f[i] - ( d[v[i].D] + 1 ) * v[i].G } );}}printf( "Case %lld: %lld\n", ++ Case, ans );}return 0; }

總結

以上是生活随笔為你收集整理的[WF2011] MachineWorks(李超树优化dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

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