Data 帶修改的主席樹 樹狀陣列套主席樹

2022-08-09 04:27:09 字數 1604 閱讀 1913

樹狀陣列套主席樹

樹狀陣列的每個節點維護的是一段區間,我們將每個區間構造成一棵線段樹,這時候如果我們要修改乙個值,只需要修改logn個節點即可,

時間複雜度為log^2(n),樹狀陣列維護的區間是數的個數n;離散化時是把所有數(包括要修改的數)全部離散化;

1.修改

在修改之前,我們應先把序列裡原來的值在主席樹對應節點+1(主席樹里維護的是某個數出現的次數),遍歷logn棵主席樹。在修改時,先把該

數原來的值的在主席樹上的對應節點+(-1),再把要修改的值在對應節點+1,並在原陣列上修改;

2.查詢區間k大

其實查詢和普通主席樹在原理上並沒有什麼區別,都是用二分,然後樹套樹就是把乙個區間的主席樹拆成了若干部分,(由樹狀陣列來完成),

例:我們要查詢區間[l,r]第k大,用乙個陣列來記錄從1到l要經過的每棵主席樹的根節點,再用另乙個陣列來記錄從1到r要經過的每棵主席樹的

根節點,利用字首和思想,在查詢時先把第乙個陣列的值的sum累加起來,另乙個也一樣,兩個陣列作差,得到的就是區間l到r的數出現的個數,

然後再用二分不斷縮小範圍,直至l==r;

luogu 2617:

1 #include2 #include3 #include4

#define lowbit(x) x&-x

5using

namespace

std;

6#define maxn 10005

7int totn=0,cnt=0,a[maxn*2],s[maxn<<1],ls[maxn*600],rs[maxn*600],val[maxn*600],rt[maxn*600],sz=0,ca[maxn*2],cb[maxn*2

],totx,toty,n,xx[maxn],yy[maxn],cc[maxn];8//

void build(int &p,int l,int r)

15//}16

void insert(int &p,int cmp,int x,int l,int r,int

v)23

else26}

27}28int query(int l,int r,int

k)38

else42}

43void add(int x,int

v)47

intread()

55return

s;56}57

intmain()

5866

for(i=1;i<=m;i++)74}

75 sort(s+1,s+totn+1

);76 sz=unique(s+1,s+totn+1)-s-1;77

for(i=1;i<=n;i++)

78 add(i,1

);79

//build(rt[0],1,sz);

80//

for(i=1;i<=n;i++)

83//

for(i=1;i<=m;i++)

87for(i=1;i<=m;i++)

95else

100}

101 }

view code

可修改主席樹 樹狀陣列套主席樹

普通主席樹可以查詢區間k小值,但若直接修改,則複雜度極大,而可修改主席樹通過樹狀陣列的輔助來修改,大大縮小了時間複雜度,缺點是空間複雜度過大.修改的時間複雜度為o logn 2 空間複雜度為o n logn 2 為了減小修改複雜度,可以修改每個區間管理的範圍.傳統主席樹每個點對應的主席樹管理乙個字首...

帶修改的主席樹

對於單點修改的主席樹,我們可以採用樹套樹來寫,原因 不會整體二分求帶修改的區間第k小。所以學習了一波 待修改的主席樹。真的是難寫,或者說碼量有點大。不過和三維偏序cdq分治相比其實差不了多少,但是cdq終究比樹套樹快而且空間消耗小。兩者都很不錯!經典題,但是對於我這個根本不懂樹套樹的人來說是有點難度...

樹狀陣列套主席樹 帶修改區間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繼續回答上面的問題。你需要編乙個這樣的程式...