樹鏈剖分的核心思想就是將乙個樹上問題轉化為鏈上問題,然後就可以用線段樹解決啦。
這裡有乙個重鏈和輕鏈的概念。找到每個節點的重兒子作為他的son存下來。將每個點和他的重兒子們作為一條鏈搞下去。
#include using namespace std;
const int maxn=400005;
int n,m,root,mod;
int tot,cnt;
int u[maxn],v[maxn],head[maxn],nxt[maxn],dep[maxn],size[maxn];
int sum[maxn],add[maxn],son[maxn],fa[maxn],a[maxn],id[maxn];
int top[maxn],wt[maxn];
void add_edge(int x,int y)
void build(int root,int l,int r)
int mid=(l+r)/2;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
sum[root]=sum[root*2]+sum[root*2+1];
}void push_down(int root,int l,int r)
}void update(int root,int l,int r,int l,int r,int k)
push_down(root,l,r);
int mid=(l+r)/2;
if(mid>=l) update(root*2,l,mid,l,r,k);
if(mid+1<=r) update(root*2+1,mid+1,r,l,r,k);
sum[root]=(sum[root*2]+sum[root*2+1])%mod;
}int query(int root,int l,int r,int l,int r)
push_down(root,l,r);
int mid=(l+r)/2;
if(mid>=l) ans+=query(root*2,l,mid,l,r);
ans%=mod;
if(mid+1<=r) ans+=query(root*2+1,mid+1,r,l,r);
return ans%mod;
}void dfs1(int x,int father,int deep) }}
void dfs2(int x,int topf)
}int qrange(int x,int y)
void uprange(int x,int y,int k)
int main()
dfs1(root,0,1);dfs2(root,root);
build(1,1,n);
for(int i=1;i<=m;i++)
if(k==2)
if(k==3)
if(k==4)
}return 0;
}
樹鏈剖分總結
樹鏈剖分思想不是很複雜。首先給出幾個定義吧 其核心思想就是,將一棵樹拆成多條鏈,然後對於每一條鏈,就用資料結構去維護。有個不會證明的性質,就是如果將一顆樹拆成多條重鏈和輕邊,那麼重鏈的個數不會超過 log 2n 輕邊的邊數也不會超過 log 2n 因為這個性質,很多操作我們可以很高效地完成。這個之後...
樹鏈剖分總結
把樹剖成鏈再操作 部落格安利 維護7個不同陣列,通常和線段樹一起使用 1 模板題 p3384 模板 樹鏈剖分 p3178 haoi2015 樹上操作 p2590 zjoi2008 樹的統計 p2146 軟體包管理器 p2420 讓我們異或吧 2 應用題 p3950 部落衝突 p3038 牧草種植 1...
模板總結 樹鏈剖分
給定一顆樹,要求對樹上的路徑 u,v 進行高效操作。1 更新路徑 u,v 上所有點的權值,單點查詢樹上某點的權值 2 更新結點u的權值,查詢路徑 u,v 上的權值和 3 更新路徑 u,v 上的權值,查詢路徑 u,v 上的權值和 4 更新結點u的權值,查詢路徑 u,v 上的lcis 5 更新結點u到根...