樹鏈剖分 樹剖換根

2022-02-04 07:32:57 字數 1548 閱讀 6827

這是一道模板題。

給定一棵 n 個節點的樹,初始時該樹的根為 1 號節點,每個節點有乙個給定的權值。下面依次進行 m 個操作,操作分為如下五種型別:

換根:將乙個指定的節點設定為樹的新根。

修改路徑權值:給定兩個節點,將這兩個節點間路徑上的所有節點權值(含這兩個節點)增加乙個給定的值。

修改子樹權值:給定乙個節點,將以該節點為根的子樹內的所有節點權值增加乙個給定的值。

詢問路徑:詢問某條路徑上節點的權值和。

詢問子樹:詢問某個子樹內節點的權值和。

第一行為乙個整數 nnn,表示節點的個數。

第二行 nnn 個整數表示第 iii 個節點的初始權值 ai​​ 。

第三行 n−1 個整數,表示 i+1號節點的父節點編號 fi+1 (1⩽fi+1⩽n)。

第四行乙個整數 m,表示操作個數。

接下來 m 行,每行第乙個整數表示操作型別編號:(1⩽u,v⩽n)

若型別為 1,則接下來乙個整數 u,表示新根的編號。

若型別為 2,則接下來三個整數 u,v,k,分別表示路徑兩端的節點編號以及增加的權值。

若型別為 3,則接下來兩個整數 u,k,分別表示子樹根節點編號以及增加的權值。

若型別為 4,則接下來兩個整數 u,v,表示路徑兩端的節點編號。

若型別為 5,則接下來乙個整數 u,表示子樹根節點編號。

對於每乙個型別為 4 或 5 的操作,輸出一行乙個整數表示答案。

#include #include #define int long long

using namespace std;

const int maxn=100003;

int n,m,a[maxn],head[maxn],cnt,root,sum[maxn<<2],tag[maxn<<2],len[maxn<<2];

int dep[maxn],fa[maxn],top[maxn],num[maxn],fnum[maxn],son[maxn],siz[maxn];

struct nodee[maxn];

void addedge(int x,int y),head[x]=cnt;}

void dfs_1(int x)

}void dfs_2(int x,int topp)

void gettag(int x,int d)

void pushdown(int x)

void pushup(int x)

void build(int x,int lef,int rig)

void add(int x,int xl,int xr,int lef,int rig,int d)

int ask(int x,int xl,int xr,int lef,int rig)

int getlca(int u,int v)

void modify_u(int u,int k)

int query_uv(int u,int v)

int query_u(int u)

signed main()

return 0;

}

樹鏈剖分換根

描述 給定一棵 n 個節點的樹,初始時該樹的根為 1 號節點,每個節點有乙個給定的權值。下面依次進行 m 個操作,操作分為如下五種型別 換根 將乙個指定的節點設定為樹的新根。修改路徑權值 給定兩個節點,將這兩個節點間路徑上的所有節點權值 含這兩個節點 增加乙個給定的值。修改子樹權值 給定乙個節點,將...

2018 08 27 模板 樹鏈剖分換根(模板)

描述 給定一棵大小為 n 的有根點權樹,支援以下操作 換根 修改點權 查詢子樹最小值 輸入第一行兩個整數 n,q 分別表示樹的大小和運算元。接下來n行,每行兩個整數f,v,第i 1行的兩個數表示點i的父親和點i的權。保證f i。如 果f 0,那麼i為根。輸入資料保證只有i 1時,f 0。接下來 m ...

遙遠的國度(樹鏈剖分,換根)

zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神rapid阻攔了zcwwzdjn的去路,他需要zcwwzdjn完成任務後才能進入遙遠的國度繼續追殺。問題是這樣的 遙遠的國度有n個城市,這些城市之間由一些路連線且這些城市構成了...