利用線段樹十分方便的處理區間,線段樹是一棵完美的二叉樹,樹上的每乙個節點都維護乙個區間,根維護的是整個區間,線段樹通常用來計算區間內資料的和或者是修改某處的值。
對區間的操作可以再o(logn)的時間內完成。
下面我們通過**實現線段樹的構建,修改,區間求和。
#include
#include
//線段樹
#define max_len 1000
//構造線段樹
void
build_tree
(int arr,
int tree,
int node,
int start,
int end)
else
}void
update_tree
(int arr,
int tree,
int node,
int start,
int end,
int idx,
int val)
else
else
//更新節點(通過搜尋到了相應的部位)
tree[node]
= tree[left_node]
+ tree[right_node];}
}int
query_tree
(int arr,
int tree,
int node,
int start,
int end,
int l,
int r)
else
if(start == end)
else
if(l<=start && r>=end )
int mid =
(start+end)/2
;int left_node =
2* node +1;
int right_node =
2* node +2;
int sum_left =
query_tree
(arr,tree,left_node,start,mid,l,r)
;int sum_right =
query_tree
(arr,tree,right_node,mid+
1,end,l,r)
;return sum_left+sum_right;
}int
main()
;int size=6;
int tree[max_len]=;
build_tree
(arr,tree,0,
0,size-1)
;return0;
}
最為重要的就是lowbit操作(類似補碼)
這樣在給陣列的某乙個值向上新增的時候就可以逐層向上操作了
**實現
int bit[max_n+1]
,n;int
sum(
int i)
return s;
}void
add(
int i,
int x)
}
b站很詳細的詳解 看前分鐘就可
並查集主要是為了找根節點,按照普通方法找的話,應該是從最深的節點往上遞迴,看看最終的根節點是哪個。(圖已經很清楚了)
上**
#include
using
namespace std;
const
int maxn =
1e6+7;
int fa[maxn]
;intfi(
int x)
void
union1
(int x,
int y)
intcheck
(int x,
int y)
intmain()
}
03 並查集 帶權,分類 樹狀陣列 線段樹
並查集板子題,記錄是否被修,然後每次修了以後更新相連的電腦。include include includeusing namespace std typedef long long ll const ll max n 2e5 100 const ll inf 0x3f3f3f3f int n,xs ...
紅綠 線段樹分治, 並查集
對 1,q to t 1,q tot 1,q t ot 進行線段樹分治,將每個 綠綠 的 影響區間分為 log q tot log q tot logq t ot個區間散布在線段樹節點中,其中 qto tq tot qt o t 為詢問的總數 然後對線段樹dfs dfsdf s,合併祖先鏈的和當前節...
bzoj 3211 樹狀陣列 並查集
題意 1 詢問 l,r 區間和 2 修改 l,r 區間的delta dalta i int sqrt delta i 思路 1 區間求和和區間修改我們可以考慮相應的資料結構 線段樹或樹狀陣列,這裡我們選擇樹狀陣列 2 開根號的性質 1 1 或 0 開根號後數值和對答案的貢獻不變,即開根號操作對0 或...