HDU 6621 主席樹 二分優化

2021-09-25 20:17:04 字數 1662 閱讀 1321

這本來應該是多校的時候用來救命的一道資料結構水題,結果當時不知道是測評機有問題還是我**不夠簡單,15s都tle了,當時很慌,也沒細想,後來重寫了一遍,6s不到過了。

題意很好理解,乙個陣列,我問你某一子區間內所有數和p

pp的差值裡,第k

kk小的是多少?

首先,這題主席樹基本不難想,要是不會主席樹可以參考我以前的部落格:[資料結構——靜態主席樹]

關鍵在於這題建好主席樹之後怎麼辦。當時標程好像是二分列舉k

kk的值,然後看查詢區間在[p−

k,p+

k]

[p-k,p+k]

[p−k,p

+k]範圍內的數個數。

我用的是另一種思路,二分列舉區間左端點。我們注意到,和p

pp距離前k

kk大的數在數值上一定是連續的。主席樹本身就是用來查詢區間第k

kk大的數的,所以,我們可以列舉這段連續區間的左端點,然後+k-1就是右端點,然後比較他們各自與p

pp的差值,如果二者在p

pp兩邊且與p

pp距離相等,那麼此時這就是最優方案。否則,如存在更優狀態,我們把與p

pp距離大的一段向中心移動一定是更優的(注意先更新x

xx的值再移動,因為移動不一定會帶來更優解,若本來就是最優解狀態,可能任何移動都會帶來更差的解)。這樣二分下去就是答案。

上**:

#include

#include

#include

using

namespace std;

const

int maxn =

1e6+10;

int n, q, m, tot;

int a[maxn]

, b[maxn]

, t[maxn]

;int ls[maxn*30]

, rs[maxn*30]

, c[maxn*30]

;void

init()

intbuild

(int l,

int r)

return rt;

}int

update

(int rt,

int pos)

else

c[nw]

= c[rt]+1

;}return res;

}int

query

(int lrt,

int rrt,

int k)

else

}return b[l];}

void

solve()

while

(q--

) e =

query

(t[l]

, t[r+1]

, mid)

, f =

query

(t[l]

, t[r+1]

, mid+k-1)

; x =

min(x,

max(

abs(e-p)

,abs

(p-f)))

;printf

("%d\n"

, x);}

}int

main()

hdu 6621 主席樹 二分

題意 給乙個陣列a,每次詢問,給定l,r,p,k,求 l r 中的數與p做差的絕對值的第k小。思路 對陣列a建立主席樹 不用離散化 對於每次詢問,二分答案,如果 l r 區間中的 p mid p mid 範圍內的數大於k,則說明二分的答案偏大,需要縮小區間 如果等於k,也需要縮小,因為要找到精確的值...

hdu 6621(主席樹模板)

hdu 6621 思路 每次查詢第k小,只有p在改變,所以我們可以列舉p的左右範圍,因為題目中保證每個值都不同,所以省略離散化,直接建立主席樹,二分尋找p的左右範圍,就是最終的答案。include using namespace std const int maxn 1e6 10 int a max...

bzoj2653 二分 主席樹

對於每乙個詢問二分答案。設當前答案為x,將 x的數的權值設為1,當 b 1,c 1 的權值和 a,b 權值和最大的字尾 c,d 權值和最大的字首 0時x可行。先對每個數離散,然後以每個值建立主席樹記錄區間和 最大字首 最大字尾就可以了。時間複雜度 o n log3n 1 include2 inclu...