筆記 樹鏈剖分

2021-08-02 04:04:52 字數 1523 閱讀 3904

樹鏈剖分:

對於每個結點 連線子節點多的那個子樹的邊叫做重邊

重邊連起來成鏈  叫重鏈 (不止是只有一條重鏈) 

使用線段樹或者其他的資料結構存重鏈 用此資料結構進行操作 

兩個dfs操作

: 第乙個dfs 求出重鏈 深度dep陣列 父節點fa陣列 和每個結點的子結點個數size陣列 知道了size才可以求出重鏈 

第二個dfs 連線重鏈 對於每個重鏈 重鏈的標號為第乙個結點的編號 belong陣列表示每個結點的所在重鏈編號 

在第二個dfs中記錄dfs序 這樣才可以形成連續的區間! 後面的操作都是pos[x] 而不是x因為在樹中的第x個不一定是資料結構中的第x個 

基礎題目 bzoj4034樹上操作

#include#include#include#include#include#include#define ll long long

#define n 200005

using namespace std;

int b[n],p[n],nt[n],fa[n],belong[n],cover[n],pos[n],v[n],sz[n];

ll sum[2*n],tag[2*n];

int n,m,cnt,num;

int read()

while(ch>='0'&&ch<='9')

return x*f;

}void dfs(int x) }}

void dfs2(int x,int idno)

if(k>0)

for(int e=p[x];e;e=nt[e]) }}

void pushdown(int l,int r,int k)

void add(int k,int l,int r,int x,int y,ll val)

int mid=(l+r)>>1;

if(x<=mid) add(k<<1,l,mid,x,min(mid,y),val);

if(y>mid) add(k<<1|1,mid+1,r,max(mid+1,x),y,val);

sum[k]=sum[k<<1]+sum[k<<1|1];

}void insert(int x,int y)

ll query(int k,int l,int r,int x,int y)

ll querysum(int x)

s+=query(1,1,n,1,pos[x]);

return s;

}int main()

dfs(1);

dfs2(1,1);

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

add(1,1,n,pos[i],pos[i],v[i]);

int t,x,a;

while(m--)

if(t==2)

if(t==3) printf("%lld\n",querysum(x));

} return 0;

}

筆記 樹鏈剖分

洛谷 樹鏈剖分模板 前置芝士 鏈式前向星,線段樹,dfs序 這裡寫的是重鏈剖分。參考部落格指盜圖 x正義小學生x 樹鏈剖分可以把一棵樹 投影 到乙個序列上,然後用線段樹維護一些東西。通過重兒子的性質來保證時間複雜度。我們首先使用兩次dfs進行預處理,將樹投影到序列上。對於乙個有兒子的節點,我們定義它...

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...

樹鏈剖分筆記 (戳)

對於樹鏈剖分,看到大佬紛紛各種躺切內心很是惶恐,於是跪著請教大佬之後把自己的一點感悟發出來以防以後忘了qwq 指一種對樹進行劃分的演算法,它先通過輕重邊剖分將樹分為多條鏈,保證每個點屬於且只屬於一條鏈,然後再通過資料結構 樹狀陣列 sbt splay 線段樹等 來維護每一條鏈 常見的剖分的方法是輕重...