Bzoj5251 線段樹 貪心

2022-05-02 02:15:11 字數 1685 閱讀 2584

bzoj5251 線段樹+貪心

記錄本蒟蒻省選後的第一篇題解!

國際慣例的題面:

首先這個東西顯然是一棵樹。

如果我們把數值排序,並建立這棵樹的dfs序,顯然dfs序上的乙個區間對應數值的乙個區間,且根為數值區間左端點。

如果你這樣想,恭喜你能獲得50分,如果記得加了eps會獲得55~60分。

因為當數值可以相同的時候,這個貪心是存在反例的。

考慮10個點的二叉堆,9個1乙個2,顯然2應該在位置6,而這樣跑出來2會在位置10!

因為可能乙個子樹的數值是不連續的,我們可以在把根節點的位置減小為相同數值的左乙個的時候,把這個區間的乙個值分給別的子樹。

考慮修正貪心。

我們離散化序列,記錄每個值出現次數。

然後我們令f[i]表示》=i的數的個數。

先統計出子樹size,考慮bfs遍歷整個子樹。

這樣我們子樹的根節點x要選擇的就是滿足f[1,i]均》=siz[x]的最大的i,我們令ans[x]=i。

之後我們需要讓f[1,i]減去siz[x],為了給這個子樹預留位置。

當然,在遍歷到乙個節點的時候需要把為他的父親預留的size加回去,也就是說,讓f[1,ans[fa[x]]]加上siz[fa[x]]-1。

這個線段樹二分怎麼實現?由於這個序列不單調,我們維護區間min,如果左區間的min>=siz[x]的話就去右區間查詢。

最後特判當前的點能否選擇即可。

(考試的時候想到了線段樹,但是非得用dfs序列遍歷,怎麼也弄不對......)

注意這題bzoj卡eps!!!!!

**:

1 #include2 #include3 #include4 #include5

#define debug cout

6using

namespace

std;

7const

int maxn=5e5+1e2;

8const

double eps=1e-8;9

10int

in[maxn],srt[maxn],siz[maxn],len;

11int

ans[maxn],fa[maxn],ts[maxn],vis[maxn];

12int

n;13

14struct

segmenttree

delta)

25 inline void push(int

pos)

29 inline void maintain(int

pos)

33 inline void update(int pos,int ll,int rr,int

delta)

40 inline int query(int pos,int

lim)

46}segt;

4748 inline void

getseq()

55 segt.build(segt.cnt=1,1

,len);

56for(int i=1;i<=len;i++) segt.update(1,1

,i,siz[i]);57}

5859 inline void calcpoint(int

x) 64

65int

main()

view code

BZOJ5251 八省聯考2018劈配(網路流)

劈配,匹配,網路流。那麼考慮怎麼跑網路流。先看第一問。首先套路的建出超源超匯。不用想也知道導師向匯連容量為戰隊人數上限的邊。特別地,給出局也建乙個點,向匯連容量inf的邊 似乎沒有必要 對於乙個新學員,假設我們已經知道了之前的學員的最優選擇,可以把之前的每名學員和可以選擇的導師連邊,並由源向學員連容...

BZOJ 4756 線段樹合併(線段樹)

思路 1.最裸的線段樹合併 2.我們可以觀察到子樹求乙個東西 那我們直接dfs序好了 入隊的時候統計一下有多少比他大的 出的時候統計一下 減一下 搞定 線段樹合併 by siriusren include include include using namespace std const int n...

BZOJ 3252 攻略 貪心 長鏈剖分 線段樹

題目鏈結 實際上,每個點只被統計一次,就是選 k 條最長的不相交的鏈 鏈形態是從上到下的 所以可以想到長鏈剖分。以路徑權值和作為深度,選最長的 k 條長鏈就行了。用nth element就可以把排序的複雜度也省了233.所以複雜度 o n 10236kb 364ms include include ...