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...