題意:有n種樹,每種樹給出高度h,砍掉每顆樹的花費c,每種樹的數量p,現在要砍掉一些樹,使得最高的樹的數量超過所有樹的一半,問最小花費。(不同種類的樹高度可能相同)
題解:列舉不同的高度,把高於它的樹都砍掉,然後比它矮的樹挑便宜的砍,使得該高度的樹佔所有樹的1/2+1。給樹按高度排序,首先可以用字尾和預處理出砍掉高於每種高度的樹的花費,然後用線段樹維護某一**區間的樹一共有多少顆,tr[1].num就是比當前高度矮的樹的總數,要砍掉的樹的數量就是tr[1].num-tot+1,tot是當前高度的樹的總數量。詢問砍掉矮的樹的花費時,當要砍的樹的數量k小於左子樹,就遞迴到左子樹,如果大於左子樹,就花費加上左子樹的花費,數量k減去左子樹的數量,然後遞迴到右子樹。當遞迴到葉子節點的時候,花費直接加上剩餘數量*該**。
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll inf
=0x3f3f3f3f3f3f3f3f
;const int maxn =
1e5+5;
ll ans,suf[maxn]
;struct tree
a[maxn]
;bool cmp
(const tree &a,
const tree &b)
struct node
tr[200*4
+1];
void
build
(int k,int l,int r)
int mid =
(l+r)/2
;build
(k*2
,l,mid)
;build
(k*2+1
,mid+
1,r);}
void
update
(int k,int cost,ll cnt)
int mid =
(tr[k]
.l+tr[k]
.r)/2;
if(cost <= mid)
update
(k*2
,cost,cnt);if
(cost > mid)
update
(k*2+1
,cost,cnt)
; tr[k]
.num = tr[k*2]
.num + tr[k*2+
1].num;
tr[k]
.sum = tr[k*2]
.sum + tr[k*2+
1].sum;
}void
query
(int k,ll cnt)
if(cnt <= tr[k*2]
.num)
query
(k*2
,cnt);if
(cnt > tr[k*2]
.num)
}int main()
build(1
,1,mx)
;sort
(a+1
,a+1
+n,cmp)
;for
(int i=n; i>
0; i--
) ll anss =
inf;
for(int i=
1; i<=n; i++
) ans =0;
ans += suf[j+1]
;if(tr[1]
.num >= tot)
query(1
,tr[1]
.num-tot+1)
;for
(int l=i; l<=j; l++
)update(1
,a[l]
.c,a[l]
.p);
anss =
min(anss,ans);}
printf
("%lld\n"
,anss);}
}
最小花費 Dijkstra
原題鏈結傳送門 d es crip tion description descri ptio n在n個人中,某些人的銀行賬號之間可以互相轉賬。這些人之間轉賬的手續費各不相同。給定這些人之間轉賬時需要從轉賬金額裡扣除百分之幾的手續費,請問a最少需要多少錢使得轉賬後b收到100元。i np ut inp...
題目1086 最小花費
題目描述 在某條線路上有n個火車站,有三種距離的路程,l1,l2,l3,對應的 為c1,c2,c3.其對應關係如下 距離s 票價 0l1l2輸入保證0每兩個站之間的距離不超過l3。當乘客要移動的兩個站的距離大於l3的時候,可以選擇從中間乙個站下車,然後買票再上車,所以乘客整個過程中至少會買兩張票。現...
1230 最小花費(spfa)
1230 最小花費 時間限制 1 sec 記憶體限制 128 mb 題目描述 在n個人中,某些人的銀行賬號之間可以互相轉賬。這些人之間轉賬的手續費各不相同。給定這些人之間轉賬時需要從轉賬金額裡扣除百分之幾的手續費,請問a最少需要多少錢使得轉賬後b收到100元。輸入第一行輸入兩個正整數n,m,分別表示...