題目描述:
有乙個oier,他有n
個演算法技能,每個技能有乙個水平值,每個技能的水平上限都是a
,設這個oier有cnt
個技能達到了a
, 設所有水平值的最小值為mi
,那麼這個oier的戰鬥力為cnt×cf+mi×cm
,現在這個oier準備去提公升自己的技能,他有m
次提公升的機會,每次提公升可以選擇某乙個技能給水平值加1,如何分配這些提公升的機會,來使得自己的戰鬥力總值最大?
輸入格式:
第一行輸入5
個整數,n,a,cf,cm,m
第二行輸入n
個整數,表示每個技能的水平值
輸出格式:
輸出最大戰鬥力值
樣例輸入:
3 5 10 1 5樣例輸出:1 3 1
12約定:
1≤n≤100000,1≤a≤10^9,0≤cf,cm≤1000,0≤m≤10^15
題解:考慮貪心的策略,由於只有將乙個技能點到a或者提公升最低技能等級才能增加戰鬥力,所以說,只有兩種操作是有意義的
1.將乙個技能點到a
2.將所有最低等級的技能都點高一級,相當於提公升最低等級一級
所以我們可以從1-n列舉將i個技能點到a級所需要的最小花費,這個東西sort一下就能搞了,顯然點滿最大的前i個花費最小,然後用剩下的技能點高最低技能,其思路就相當於把剩下的水倒進低窪,去獲得此時水的高度一樣
這個高度顯然是可以二分的
用lower_bound搞出高度大於等於high的第乙個位置pos,然後顯然pos-1位置都是要填的,至於要填多少,顯然可以維護乙個字首和記錄已經填了多少了,再用high*(pos-1)-這個數就可以知道你要填多少,然後和你還剩的數比下哪個大就知道了,這東西是單調的,所以可以二分
不過要注意如果你已經把i個數點到a了,那麼pos的最大位置也就是n-i了
其次開局已經到a的技能還要特殊處理一下
**如下:
#include#include#include
#include
#include
#define mod 1000000007
using
namespace
std;
long
long a[100010],n,aa,cf,cm,m,sum[100010
],tot;
int check(long
long high,long
long remain,int
now)
return0;
} intmain()
sort(a+1,a+n+1
);
while(a[n]==aa)
for(int i=1;i<=n;i++)
long
long cnt=0,ans=0
;
long
long l=1,r=1e9,mid,re=m-cnt;
while(l<=r)
else
if(r-l<=1
)
}ans=r*1ll*cm+tot*1ll*cf;
for(int i=1; i<=n; i++)
long
long l=1,r=1e9,mid,re=m-cnt;
while(l<=r)
else
if(r-l<=1
)
}ans=max(1ll*(i+tot)*cf+1ll*r*cm,ans);
}printf(
"%lld\n
",ans);
}
思路其實很簡單,但是真的是細節很多啊qaq
xjoi 二分查詢 道路規劃
70分 n 2 lis include include include include using namespace std int n,nor 100010 sou 100010 c 100010 q 100010 dp 100010 ans 0 int main for int i 1 i n...
新技能 二分答案
本來在刷圖論裡的題的,結果不小心遇到了這道luogu1462 想了好久也沒做出來,只有看題解了 怪我咯,略略略 好吧,這題要用二分 1.二分思想 其實和數學中的是一樣的,對於乙個單調函式,可以通過二分法來提高效率,從而更快的確定答案的範圍 或值 對於有單峰的函式,我們可以通過三分法來解決問題 2.二...
二分貪心 21
題目大概 有n堆積木,積木高度不同,每個小方塊高度相同。問,最少移動多少小方塊,使得這些積木堆高度相等。思路 先求這些積木的平均數,在把所有的高度與平均數的差值加起來,最後除2,就是最少移動的方塊數。感想 這個題有一點很坑人,最後輸出的時候有乙個小點,不注意看看不到。include include ...