線段樹與樹狀陣列的對比應用

2022-08-10 19:45:15 字數 1952 閱讀 8921

因為樹狀陣列不需要構造這一過程,所以先講線段樹的構造

就是用到遞迴:先設left=1,right=n,然後每一次遞迴,left、mid和mid+1、right。**如下:

void build(int left,int right,int index)

單點修改就是每到乙個節點,看這個節點代表著的區間包括不包括這個點,包括就加上。

void my_plus(int index,int dis,int k)

這裡有乙個很關鍵的東西,叫做lowbit,lowbit是將乙個二進位制數的所有高位一都去掉,只留下最低位的1,比如lowbit(5)=lowbit(0101(二進位制))=0001(二進位制)

而如果改變x的值,就要加上自己的lowbit,一直加到n,這些節點都要加,比如一共有8個數第3個數要加上k,那麼c[0011]+=k;

c[0011+0001] (c[0100])+=k;

c[0100+0100] (c[1000])+=k;

這樣就能維護樹狀陣列

void add(int x,int k)

}

區間查詢就是,每查到乙個區間,有三種選擇:

1、如果這個區間被完全包括在目標區間內,那麼加上這個區間的和,然後return;

2、如果這個區間的right>目標區間的left,那麼查詢這個區間;

3、如果這個區間的left《目標區間的right,也查詢這個區間;

void search(int index,int l,int r)

if(tree[index*2].right>=l)

search(index*2,l,r);

if(tree[index*2+1].left<=r)

search(index*2+1,l,r);

}

就是字首和,比如查詢x到y區間的和,那麼就將從1到y的和-從1到x的和。

從1到y的和求法是,將y轉為2進製,然後一直減去lowbit(y),一直到0

比如求1到7的和

ans+=c[0111];

ans+=c[0111-0001(0110)];

ans+=c[0110-0010(0100)];

ans+=c[0100-0100(c[0]無意義,結束)]

int sum(int x)

return ans;

}

和線段樹區間查詢類似,分為三種

1、如果當前區間完全屬於要加的區間,那麼這個區間,也就是節點加上,然後return;

2、如果這個區間的right>目標區間的left,那麼查詢這個區間;

3、如果這個區間的left《目標區間的right,也查詢這個區間;

void pls(int index,int l,int r,int k)

if(tree[index*2].right>=l)

pls(index*2,l,r,k);

if(tree[index*2+1].left<=r)

pls(index*2+1,l,r,k);

}

這就會變的很好玩。如果將x到y區間加上乙個k,那就是從x到n都加上乙個k,再從y+1到n加上乙個-k

加的移動還是i+=lowbit(i);

void add(int x,int k)

}

就是從根節點,一直搜尋到目標節點,然後一路上都加上就好了。

void search(int index,int dis)

從x點,一直x-=lowbit(x),沿途都加上就好啦

int search(int x)

return ans;

}

樹狀陣列與線段樹

推一下關於樹狀陣列的講解部落格 和線段樹的講解 package test2 public class 線段樹 int len a.length segtree t buildtree 0,len 1,a int sum0 2 query t,0,2 int sum1 3 query t,1,3 查詢...

樹狀陣列與線段樹(三)

找規律題 1.螺旋折線 如下圖所示的螺旋折線經過平面上所有整點恰好一次。對於整點 x,y 我們定義它到原點的距離 dis x,y 是從原點到 x,y 的螺旋折線段的長度。例如 dis 0,1 3,dis 2,1 9 給出整點座標 x,y 你能計算出 dis x,y 嗎?輸入格式 包含兩個整數 x,y...

樹狀陣列與線段樹(二)

樹狀陣列 1.小朋友排隊 n n 個小朋友站成一排。現在要把他們按身高從低到高的順序排列,但是每次只能交換位置相鄰的兩個小朋友。每個小朋友都有乙個不高興的程度。開始的時候,所有小朋友的不高興程度都是 0 0 如果某個小朋友第一次被要求交換,則他的不高興程度增加 1 1 如果第二次要求他交換,則他的不...