主席樹 思維 HDU 6703

2021-10-24 16:15:40 字數 1784 閱讀 3957

ccpc網路預選賽的題目,挺有意思的。

題目大意:

給你乙個排列.然後q次操作,兩種:

1.將乙個數 + 1e7.

2.查詢不屬於[1,

r]

[1,r]

[1,r

]的且≥

k\geq k≥k,

q≤1e

5,k≤

nn,q\leq1e5 , k \leq n

n,q≤1e

5,k≤

n 題目思路:

看到操作2應該要自然聯想到主席樹了。。查詢區間大於某個數的最小值.

因為它是乙個排列.所以結果最大也就是 n + 1.所以操作一相當於刪除乙個數.

刪除乙個數的影響? 考慮一次查詢2:r,k.

若 刪除的數 ∉

\notin

∈/​ [1,

r]

[1,r]

[1,r

].那麼對最終結果無影響。

若 刪除的數 ∈

\in∈[1,

r]

[1,r]

[1,r

]那麼可以將這個被刪的數視作在範圍[r+

1,n]

[r+1,n]

[r+1,n

].所以我們可以維護乙個set存當前已經刪除的數.然後對[r+

1,n]

[r+1,n]

[r+1,n

]主席樹上找大於等於k的最小值。得到的結果與set中找的結果取最小值即可。

複雜度的思考:

首先說結論:o(n

logn

)o(nlogn)

o(nlog

n)為什麼?

雖然我們是在主席樹上搜尋。但是無論如何,我們**的邏輯是在向區間[k,

k]

[k,k]

[k,k

]逼近的。

我們可以這麼去理解這個過程:先跑到[k,

k]

[k,k]

[k,k

]檢視是否有答案。然後在返回的過程中,檢查每個右子樹的sz.若右子樹的 sz 不為0.那麼就進入右子樹。一旦進入右子樹,那麼答案一定就存在了。所以最差情況,也就遍歷兩條鏈。單次複雜度:o(l

ogn)

o(logn)

o(logn

) ac**:

#include

using

namespace std;

#define mid ((l + r)>>1)

const

int maxn =

1e5+5;

const

int inf =

1e9;

int sum[maxn <<5]

, ls[maxn <<5]

, rs[maxn <<5]

, rt[maxn]

, tot;

int add (

int l ,

int r ,

int t ,

int p)

int ask (

int u ,

int v ,

int l ,

int r ,

int k)

set<

int> s;

int a[maxn]

;int

main()

int lastans =0;

while

(m--

)else}}

return0;

}

HDU 6703 array 權值線段樹

先不考慮修改的情況,對所有的權值建一顆線段樹,然後線段樹上儲存下標的資訊,然後每個結點維護子樹下標的最大值。然後對於每次查詢,我直接查詢區間 k,n 1 k,n 1 k,n 1 這段區間值大於r的最小的那個點。對於修改的情形,實際上每個節點被修改之後相當於刪除,也就是說該節點是可選的,把該節點的下標...

HDU6703 array(權值線段樹)

考慮建權值線段樹,那麼線段樹存的值就是它的座標,考慮到答案一定存在且最大值為n 1 n 1n 1,可以多加乙個點n 1 n 1n 1對於操作1 1,x 1,x 1,x 直接單點修改位置s x s x s x 為n 1 n 1n 1 s x 為初始位置x的值 對於操作2 2,r,x 2,r,x 2,r...

HDU4417(主席樹計數)

解題思路 如果說用排序,那麼複雜度就是o mnlogn 會超時。用主席樹的空間複雜度是o nlogn 時間複雜度是o max nlogn,mlogn 這道題稍微修改一下query函式即可。include include include include define n 100009 using na...