# 线段树 树状数组 并查集

#include <iostream>
#include <cstdio>
//线段树
#define MAX_LEN 1000
//构造线段树
void build_tree(int arr[],int tree[],int node,int start,int end){
//start 数组的start
//end 数组的end
//node是根节点
if(start == end){
tree[node] = arr[start];
//如果到下面了然后就把tree赋值了
}
else{
int mid=(start+end)/2;
//分一半
int left_node = 2 * node + 1;
//左边的坐标
int right_node = 2 *node + 2;
//右边的坐标
build_tree(arr,tree,left_node,start,mid);
//往下面造树
build_tree(arr,tree,right_node,mid+1,end);
tree[node]=tree[left_node]+tree[right_node];
//节点等于左右相加和
}
}
void update_tree(int arr[],int tree[],int node,int start,int end,int idx,int val){
if(start == end){
arr[idx] = val;
//到最底下那个要找的点的时候
//就给那个点赋值
tree[node] = val;
}else{
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
if(idx >= start && idx <= mid){
//往左右分散开来
update_tree(arr,tree,left_node,start,mid,idx,val);
} else{
update_tree(arr,tree,right_node,mid+1,end,idx,val);
}
//更新节点（通过搜索到了相应的部位）
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) {
if(R<start || L>end){
return 0;
//不在计算范围之内
}else if(start == end){
return tree[node];
//到了最下面
}else if(L<=start && R>=end ){
return tree[node];
//在区间内就直接用 不用进行多余的运算
}
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 arr[]={1,3,5,7,9,11};
int size=6;
int tree[MAX_LEN]={0};
build_tree(arr,tree,0,0,size-1);
return 0;
}

• ## 树状数组（玄学）

1 + lowbit(1)=2;
2 + lowbit(2)=4;
4 + lowbit(4)=4;
3 + lowbit(3)=4;

int bit[MAX_N+1],n;
int sum(int i){
int s = 0;
while(i>0){
s+=bit[i];
i -=(i&-i);
}
return s;
}
while (i<=n){
bit[i] += x;
i+=i&-i;
//向上进行操作
}
}


B站很详细的详解 看前分钟就可

## 并查集

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
int fa[maxn];
int fi(int x){
return fa[x]==x?x:fa[x]==fi(fa[x]);
//如果自己是根节点返回自己
//反正返回自己的上一级节点
}
void union1(int x,int y){
int p1=fi(x);
//做这个就相当于把x连接到根节点上了
int p2=fi(y);
//同理
//如果x等于y那么就退出
if(x==y)return;
fa[x]=y;
}
int check(int x,int y){
int p1=fi(x),p2=fi(y);
if(p1==p2)return 1;
//如果根节点一样就返回1喽
else return 0;
}
int main(){
for(int i=0li<maxn;i++){
fa[i]=i;
//进行初始化
}
}


04-10 1万+
05-09 1003

06-18 419
02-03 313
10-04 23
10-16 111
08-15 864