bzoj 5321(二分 優先佇列 線段樹)

2022-07-13 10:03:11 字數 3356 閱讀 8461

給你乙個長度為n

n的陣列, 以及m

m個連續的區間。現在讓你取恰好k

k個區間,你要將你選取的k

k個區間都加上a

a。現在要你最大化整個陣列的最小值,即要最大化min

⁡min

最大化最小值,看到這樣的詞彙就非常二分了,於是乎我們就考慮採用二分答案解決。

於是乎,我們現在需要考慮的就是如何進行check

check

我們首先考慮哪些如何選取這k

k個區間才能使得我們的結果最優。乙個貪心的選法就是,選擇的區間一定要覆蓋最小值的區間,同時區間的大小要盡可能的大。

因此我們可以考慮先將區間根據左端點的大小排序,然後當我們二分出乙個答案mid

mid的時候,我們先遍歷整個陣列,而在遍歷的過程中,我們把能夠包涵該端點的所有區間(即l

<

i)都壓入乙個容器中。而若當前的位置的值小於我們所二分的答案mid

mid,則我們考慮使用容器中的區間進行更新。而根據我們之前所說的貪心的選法,我們明顯需要優先選取右端點距離遠的區間,因此我們此時我們只需要用乙個優先佇列對符合條件的區間進行維護即可。

最後,倘若我們發現沒有符合條件的區間,亦或者我們選取的區間個數大於k

k,則證明當前二分值mid

mid過大,此時我們只需要將r

r左移即可。

最後,上述演算法也僅涉及區間更新以及單調查詢,因此我們可以用線段樹或者差分樹狀陣列進行維護。整體的時間複雜度為:o(n

log2

n)o(

nlog

2n)

#include

#define maxn 200005

using

namespace std;

typedef

long

long ll;

typedef pair<

int,

int>pll;

struct sttr[maxn<<2]

;int a[maxn]

;void

push_up

(int rt)

void

push_down

(int rt)

}void

build

(int l,

int r,

int rt)

int mid=

(l+r)

>>1;

build

(l,mid,rt<<1)

;build

(mid+

1,r,rt<<1|

1);push_up

(rt);}

void

update

(int l,

int r,

int l,

int r,

int rt,

int c)

int mid=

(l+r)

>>1;

push_down

(rt);if

(l<=mid)

update

(l,r,l,mid,rt<<

1,c);if

(r>mid)

update

(l,r,mid+

1,r,rt<<1|

1,c)

;push_up

(rt);}

ll query

(int l,

int r,

int l,

int r,

int rt)

int mid=

(l+r)

>>1;

push_down

(rt)

; ll res=0;

if(l<=mid) res+

=query

(l,r,l,mid,rt<<1)

;if(r>mid) res+

=query

(l,r,mid+

1,r,rt<<1|

1);return res;

}priority_queueque;

pll q[maxn]

;int n,m,k,a;

bool

judge

(ll x)

while

(query

(i,i,

1,n,1)

}return

true;}

intmain()

for(

int i=

1;i<=m;i++

)sort

(q+1

,q+1

+m);

ll l=minn,r=minn+k*a;

while

(ljudge

(l))

printf

("%lld\n"

,l);

else

printf

("%lld\n"

,l-1);

}}

#include

#define maxn 200005

using

namespace std;

typedef

long

long ll;

typedef pair<

int,

int>pll;

int a[maxn]

;ll bit[maxn<<1]

;priority_queueque;

pll q[maxn]

;ll lowbit

(ll x)

void

update

(int pos,ll c)

}ll query

(int pos)

return res;

}int n,m,k,a;

bool

judge

(ll x)

for(

int i=

1;i<=n;i++

)while

(query

(i)}return

true;}

intmain()

for(

int i=

1;i<=m;i++

)sort

(q+1

,q+1

+m);

ll l=minn,r=minn+k*a;

while

(ljudge

(l))

printf

("%lld\n"

,l);

else

printf

("%lld\n"

,l-1);

}}

Processor 二分搜尋,優先佇列

題意 給出n個任務完成區間以及工作量,求出最快處理速度.思路 用二分搜尋匹配最優速度,其中還用到優先佇列輔助.列舉所有截止時間,在此時間內的都進隊,按照工作截止時間越早越先出隊,如果截止時間不及列舉的截止時間,則錯過 include include include include includeus...

LA4254 二分 貪心 優先佇列

題目 有n個任務,每個任務有三個引數ri,di,wi,表示任務i必須在 ri,di 內執行完,現有一台處理器,處理器執行的速度可以變化,速度為s時,乙個工作量為wi的任務執行的時間為w s,任務不一定連續執行,現在要求求出處理器在執行過程中最大速度的最小值。分析 首先一定是個二分,所以主要的地方在於...

hiho 1269 優化延遲 二分 優先佇列

簡要題意 給定計算懲罰值的公式,求出不超過某閾值最小的快取大小。題目裡頭說的東西很明白,就是個堆。懲罰值應該是單調遞減的,然後直接二分快取大小再去用堆來模擬,進行判斷。做的時候某個ll寫成了int,然後後面被64位整數的輸入輸出坑了,換cin過掉。include include include in...