題目鏈結
對乙個序列進行兩種操作:
對於不待修改的區間第k
kk小,我們可以用主席樹完成。
我們來看看只用主席樹如何完成帶修改的區間第k
kk小。
對於每次修改,我們都需要把當前位置及以後的主席樹都進行修改。因此每次修改的時間複雜度為o(n
log(
n)
)o(nlog(n))
o(nlog
(n))
,空間增加o(n
log(
n)
)o(nlog(n))
o(nlog
(n))
,n
nn次操作直接**。查詢操作依舊是o(l
og(n
))
o(log(n))
o(log(
n))。
下面考慮加上樹狀陣列後的情況。
我們把樹狀陣列的每個點都改為一棵主席樹,樹狀陣列的每次修改操作都需要修改log
(n
)log(n)
log(n)
個節點,由於每個節點都是主席樹,所以每次修改時間複雜度為o(l
og2(
n)
)o(log^2(n))
o(log2
(n))
,空間增加o(l
og2(
n)
)o(log^2(n))
o(log2
(n))
,比較優秀。
注:此題還需要離散化
普通主席樹中第i
ii棵主席樹維護的是1到i
1到i1到
i這段區間的權值資訊。
而樹狀陣列套主席樹中的第i
ii棵主席樹,維護樹狀陣列中第i
ii個點所維護的點的權值資訊,即: 在普通樹狀陣列第7
77個點維護 節點1,2
,4
1,2,4
1,2,
4的和。那麼樹狀陣列套主席樹的第7
77個點就維護節點1,2
,4
1,2,4
1,2,
4的權值資訊。
空間要開很大(此處感謝趙隊)
只用待修的主席樹常數較大,姿勢不對就會超時。
正確操作:
普通主席書維護原序列的資訊,帶修改的主席樹維護修改的資訊
#include
using
namespace std;
typedef
long
long ll;
const
int maxn =
2e5+20;
const
int mod =
1e9+7;
const
int inf =
0x3f3f3f3f
;int cnt =
0, s[maxn]
,t[maxn]
, l[maxn <<8]
, r[maxn <<8]
, sum[maxn <<8]
;int
build
(int l,
int r)
return rt;
}int
update
(int pre,
int l,
int r,
int x,
int val)
return rt;
}int
lowbit
(int x)
int used[maxn]
,n,m;
void
add(
int x,
int pos,
int val)
intquery
(int t1,
int t2,
int u,
int v,
int l,
int r,
int k)
else
}struct node
q[maxn]
;int book[maxn]
,h[maxn]
;int
gethash
(int x,
int len)
intmain()
else
if(id ==
'q')
}sort
(h,h+now)
;int num=
unique
(h,h+now)
-h;for
(int i=
1;i<=n;i++
)t[i]
=update
(t[i-1]
,0,2e5+10
,gethash
(book[i]
,num),1
);for(
int i=
0;i)else
if(q[i]
.id==
'q')
}return0;
}
樹狀陣列套主席樹 帶修改區間K大數
題目描述 給定乙個含有n個數的序列a 1 a 2 a 3 a n 程式必須回答這樣的詢問 對於給定的i,j,k,在a i a i 1 a i 2 a j 中第k小的數是多少 1 k j i 1 並且,你可以改變一些a i 的值,改變後,程式還能針對改變後的a繼續回答上面的問題。你需要編乙個這樣的程式...
Data 帶修改的主席樹 樹狀陣列套主席樹
樹狀陣列套主席樹 樹狀陣列的每個節點維護的是一段區間,我們將每個區間構造成一棵線段樹,這時候如果我們要修改乙個值,只需要修改logn個節點即可,時間複雜度為log 2 n 樹狀陣列維護的區間是數的個數n 離散化時是把所有數 包括要修改的數 全部離散化 1.修改 在修改之前,我們應先把序列裡原來的值在...
動態區間第K大 樹狀陣列 主席樹
很早以前做靜態第k大的時候聽到要用樹套樹就過於害怕逃走了,現在用分塊暴力過了之後又想用樹套樹a一遍,於是就寫了一下 starkmal的線段樹 splay常數卡出翔惹 prag ma gcc optimize o3 include include include include include inc...