處理以節點x為根的整個子樹:用線段樹處理[pos[x],pos[x]+siz[x]-1]即可
查詢節點x和節點y的lca(最近公共祖先):將兩點不斷向上挪動並處理,直到兩點的top相同,deep小的點即是最近公共祖先
處理節點x到節點y的路徑上的點:將兩點不斷向上挪動並處理,直到兩點的top相同,最後用線段樹處理[pos[x],pos[y]]即可
處理節點x到節點y的路徑上的邊:將兩點不斷向上挪動並處理,直到兩點的top相同,最後用線段樹處理[pos[son[x]],pos[y]]即可(用每個點表示通向其父節點的邊)
以洛谷模板題為例給出**:
#include
using
namespace
std;
const
int maxn=100010;
struct linel[maxn<<1];
int n,m,r,p,left,right,x,y,z,type,cnt=0;
int fa[maxn],deep[maxn],son[maxn],siz[maxn],fi[maxn];
int top[maxn],pos[maxn],num=0,in[maxn],temp[maxn];
int t[maxn<<2],delta[maxn<<2];
int read()
void make_line(int x,int y)
void dfs(int x,int f,int d)
} top[x]=tp;pos[x]=++num;
if(son[x])dfs2(son[x],tp);
for(int i=fi[x];i;i=l[i].next)
}void make_tree(int l,int r,int root)
int mid=(l+r)>>1;
make_tree(l,mid,root<<1);
make_tree(mid+1,r,root<<1|1);
t[root]=t[root<<1]+t[root<<1|1];
}void push_down(int l,int r,int root)
void add(int l,int r,int root)
int mid=(l+r)>>1;
push_down(l,r,root);
add(l,mid,root<<1);
add(mid+1,r,root<<1|1);
t[root]=t[root<<1]+t[root<<1|1];
return;
}long
long find(int l,int r,int root)
void change()
left=pos[tb];right=pos[b];
add(1,n,1);//分段處理
b=fa[tb];tb=top[b];
}if(deep[a]>deep[b])swap(a,b);
left=pos[a];
right=pos[b];
add(1,n,1);//同一重鏈後的處理
}void query()
left=pos[tb];right=pos[b];
ans+=find(1,n,1);//同上
ans%=p;
b=fa[tb];tb=top[b];
}if(deep[a]>deep[b])swap(a,b);
left=pos[a];
right=pos[b];
ans+=find(1,n,1);
ans%=p;
printf("%lld\n",ans);
}void work()
if(type==4)
}}int main()
模板先到這裡,還有很多題要做…… 樹鏈剖分 樹鏈剖分講解
好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 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...
樹鏈剖分 樹剖換根
這是一道模板題。給定一棵 n 個節點的樹,初始時該樹的根為 1 號節點,每個節點有乙個給定的權值。下面依次進行 m 個操作,操作分為如下五種型別 換根 將乙個指定的節點設定為樹的新根。修改路徑權值 給定兩個節點,將這兩個節點間路徑上的所有節點權值 含這兩個節點 增加乙個給定的值。修改子樹權值 給定乙...
演算法入門 樹鏈剖分 輕重鏈剖分
目錄 3.0 求 lca 4.0 利用資料結構維護資訊 5.0 例題 參考資料 資料結構入門 線段樹 發表於 2019 11 28 20 39 dfkuaid 摘要 線段樹的基本 建樹 區間查詢 單點修改 及高階操作 區間修改 單點查詢 區間修改 區間查詢 標記下傳 標記永久化 閱讀全文 樹鏈剖分用...