砍樹最小花費

2021-10-01 22:43:14 字數 2085 閱讀 4804

題意:有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,分別表示...