[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? 當成 kkk,dpj?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)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网页浮窗怎么关闭(如何关闭网页浮窗)
- 下一篇: 【学习笔记】Miller-Rabin(米