有n個隊友和m個敵人,每個隊友有乙個攻擊力ai,每個敵人有攻擊力bi和價值ci。你可以選擇若干個隊友,每個隊友i去懟乙個敵人j(i,j兩兩不同),當ai>bj時,你的隊友可以對答案造成ai-bj+cj的貢獻。問答案最大可以是多少。
n,m≤100000
我首先往貪心方面想。
考慮把隊友按a公升序排序,敵人按b公升序排序。然後列舉攻擊力,開乙個優先佇列維護可以懟的敵人的c-b。然後對於乙個對友,如果在佇列裡有人可以懟,那麼把這個人刪去並加上相應的答案,否則就換掉乙個a最小的隊友(顯然可以)。
但是這樣做會錯,因為你求的是在選擇的隊友最多情況下的答案。有敵人c-b為負數時會錯,這時應該捨棄掉一些敵人。
按照上面的方法可以跑出乙個解,之後要做的是:把用到的隊友和懟掉的敵人存下來,然後每次刪掉a最小的隊友和c-b最小的敵人,得到另乙個解(這樣刪仍然合法,因為隊友從小到大刪不會產生不合法配對),並更新答案。
時間複雜度o(
(n+m
)log
(n+m
))
#include
#include
#include
#include
using
namespace
std;
const
int n=2e5+5;
typedef
long
long ll;
int n,m,h,t,d[n];
ll ans,s;
priority_queue f;
priority_queue ,greater > g;
struct data
a[n];
bool
operator
< (const data &a,const data &b)
int main()
for (int i=0;i1;
}sort(a,a+n);
h=1;
for (int i=0;iif (a[i].typ==1) f.push(a[i].y);else
}else}}
ans=s;
for (int i=h;i<=t;i++)
printf("%lld\n",ans);
return
0;}
bzoj4977 跳傘求生 貪心
題目 今天講的貪心題,真神奇啊 首先,要得到盡量多選隊友的解 把隊友按 a i 從小到大排序,敵人按 b i 從小到大排序,然後對於每個隊友,選擇能攻擊的 收益最多的敵人 如果沒有能攻擊的敵人,就把之前最小的乙個隊友踢掉代替,能使答案更優 但盡量多選隊友不一定是最終的最優答案,因為有些價值很小 為負...
bzoj2078 求樹的重心
時間限制 1 sec 記憶體限制 128 mb 樹的重心定義為樹的某個節點,當去掉該節點後,樹的各個連通分量中,節點數最多的連通分量其節點數達到最小值。樹可能存在多個重心。如下圖,當去掉點1後,樹將分成兩個連通塊 2,4,5 3,6,7 則最大的連通塊包含節點個數為3。若去掉點2,則樹將分成3個部分...
BZOJ 1001 最短路求最小割
對於這道題,是乙個裸的求一張圖最小割的問題,可是資料太大,dinic過不了,注意到題目中的圖是平面圖,因此我們可以通過將平面圖轉化為對偶圖的形式在對偶圖中跑最短路,這樣就可以用spfa或堆優化的dijkstra來做了 include include include includeusing name...