題目描述
小明很喜歡打遊戲,現在已知乙個新英雄即將推出,他同樣擁有四個技能,其中三個小技能的釋放時間和固定的傷害值為:
他還有乙個大招,其釋放的時間是乙個區間【l,r】,可以在區間內任意時間點釋放出技能,其如果在l+i時刻釋放技能,其能夠打出的傷害值為:temp+a*i
這裡temp值表示技能的基礎傷害(同時也就是在時刻l釋放技能的傷害值),a是乙個常數。
小明很喜歡研究連招使得在有限的時間內打出最高的傷害,現在他想要在t長度單位時間內打出最高的傷害,問這個最大傷害值。
輸入描述:
本題包含多組資料。輸入格式為:
tx a
y bz c
l r temp a
資料範圍:
1<=t<=1e5
1<=x,y,z,l,r<=t
l<=r
<=a,b,c,temp,a<=1e5
輸出描述:
輸出包含一行,輸出能夠打出的最高傷害值。示例1
輸入
83 12 3
1 33 3 3 3
輸出
24備註:
大招:蓄力時間最短l秒,最多r秒。無限次釋放,釋放之後照成的傷害是隨著時間增加的題意:小明有三個小技能和乙個大招,每個小技能消耗ai的時間,打出bi的傷害,大招的基礎傷害為temp,基礎時間為l,大招可以蓄力,得到的傷害為temp+(t-l)*a,其中t為大招的時間,上限為r,求總時間為t打出的最高傷害蓄力l秒釋放能夠造成temp的傷害
蓄力l+1秒釋放能夠造成temp+1*a的傷害
依次類推
題解:對於三個小技能可以直接使用普通的揹包dp,而對於大招,如果暴力地把大招時間拆成l,l+1....r,那麼複雜度將是o(n^2),很明顯會超時,而觀察到對大招來說dp[i]=max(dp[j]+temp+a*(i-l-j)),所以對於j>k, 如果 j 相對於k更優,那麼(dp[j]+temp+a*(i-l-j)) - (dp[k]+temp+a*(i-l-k)) > 0,所以有dp[j]-dp[k]>a*(j-k),可以使用斜率優化dp,而由於這裡的a為常數,和 i 無關,所以可以直接知道當前點是否最優,不需要維護凸包,也就是可以不使用斜率優化dp,而使用單調佇列優化dp(斜率優化dp和單調佇列優化dp區別就在插入新點時前者是維護凸包後者是維護單調佇列)
斜率優化dp
#include#includeview code#include
#include
#include
#include
#include
using
namespace
std;
//#define io_test
#define debug(x) cout
long
long
ll;ll dp[
100005],pq[100005
];int
main()
if(i>=y)
if(i>=z)
if(i>=l)
while(tail-head>=1&&(dp[i-l+1]-dp[pq[tail]])*(pq[tail]-pq[tail-1])>(i-l+1-pq[tail])*(dp[pq[tail]]-dp[pq[tail-1]]))tail--;//
維護凸包
++tail;
pq[tail]=i-l+1
; }
}printf(
"%lld\n
",dp[t]);
}return0;
}
單調佇列優化dp
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8view codeusing
namespace
std;9//
#define io_test
10#define debug(x) cout<11 typedef long
long
ll;12 ll dp[100005],pq[100005
];13
intmain()
1434
if(i>=y)
37if(i>=z)
40if(i>=l)
45while(tail>=head&&(dp[i-l+1]-dp[pq[tail]])>a*(dp[i-l+1]-dp[pq[tail]]))tail--;//
維護單調佇列
46 ++tail;
47 pq[tail]=i-l+1
; 48}49
}50 printf("
%lld\n
",dp[t]);51}
52return0;
53 }
這題還有乙個揹包的寫法,因為大招的傷害和時間的關係是條直線,所以最後的結果一定是若干小技能+若干次不蓄力大招+若干次蓄滿力大招+一次不滿的大招(注意只會使用一次不滿的大招,這點決定了可以直接揹包而不會t掉),也就是說真正需要暴力列舉的大招時間只有一次,也就是那次沒有滿的大招,所以複雜度就是o(n)
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8view codeusing
namespace
std;9//
#define io_test
10#define debug(x) cout<11 typedef long
long
ll;12 ll dp[100005],pq[100005
];13
intmain()
1434
if(i>=y)
37if(i>=z)
40if(i>=l)
43if(i>=r)46}
47for(int i=l;i<=r;i++)
50 printf("
%lld\n
",dp[t]);51}
52return0;
53 }
整理 斜率or單調佇列優化dp
題意 求乙個序列的子區間滿足長度大於k且所有數平均值最大 周源 裡的題。之前有人說周源講的是錯的 其實應該是沒什麼問題的 可以o n 求出 不過這題hdu上的資料不知道怎麼了 反正我在網上找的ac 們全都tle。總之 意思明白就好 反正也是入門題 include include include in...
單調佇列DP 斜率DP
考慮到知識點是單調佇列,考慮怎麼使用單調佇列 首先說明一點,小天使可以選擇當前時刻鋼琴是否移動 並非一次就要一段時間 考慮dp方程,由於每次只能走乙個方向,選擇不了,其實就相當於乙個一維的dp了 以往上 北 為例 t為第t段時間 f t i j max 變形為 f t i j max i 然後把 f...
揹包dp 小明打聯盟
這個題是乙個完全揹包問題,對於大招,我們有三種選擇 l,l i,r l,l i,r l,l i,r,最終的方案中l i l i l i最多出現一次,於是先用前三個 物品 l r 前三個物品 l r 前三個物品 l r這五個物品跑完全揹包,然後用l i l i l i更新一遍dp v dp v dp ...