描述
給定一棵大小為 n 的有根點權樹,支援以下操作:
• 換根
• 修改點權
• 查詢子樹最小值
輸入第一行兩個整數 n, q ,分別表示樹的大小和運算元。
接下來n行,每行兩個整數f,v,第i+1行的兩個數表示點i的父親和點i的權。保證f < i。如 果f = 0,那麼i為根。輸入資料保證只有i = 1時,f = 0。
接下來 m 行,為以下格式中的一種:
• v x y表示把點x的權改為y
• e x 表示把有根樹的根改為點 x
• q x 表示查詢點 x 的子樹最小值
輸出對於每個 q ,輸出子樹最小值。
樣例輸入
3 7
0 1
1 2
1 3
q 1
v 1 6
q 1
v 2 5
q 1
v 3 4
q 1樣例輸出
1 2 3 4
提示對於 100% 的資料:n, q ≤ 10^5。
標籤leo
**訓練ing。。。
先做了一道換根樹剖的板子,調了很久發現lca寫錯了也是很感動。。。
**:
#include
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (t[p].l+t[p].r>>1)
#define n 100005
using
namespace
std;
inline
int read()
inline
void write(int x)
int n,q,fa[n],first[n],top[n],dep[n],hson[n],siz[n],num[n],pred[n],a[n],rt,cnt=0,tot=0;
struct edgee[n<<1];
struct nodet[n<<2];
inline
void dfs1(int p)
}inline
void dfs2(int p,int tp)
}inline
int min(int a,int b)
inline
void build(int p,int l,int r)
build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}inline
void update(int p,int k,int v)
if(k<=mid)update(lc,k,v);
else update(rc,k,v);
pushup(p);
}inline
int query(int p,int ql,int qr)
inline
int lca(int x,int y)
if(dep[x]return hson[y];
}inline
void add(int u,int v)
int main()
dfs1(1),dfs2(1,1),build(1,1,n);
while(q--)
}puts("");
}else
if(s[0]=='e')rt=read();
else
}exit(0);
return
0;}
樹鏈剖分 樹剖換根
這是一道模板題。給定一棵 n 個節點的樹,初始時該樹的根為 1 號節點,每個節點有乙個給定的權值。下面依次進行 m 個操作,操作分為如下五種型別 換根 將乙個指定的節點設定為樹的新根。修改路徑權值 給定兩個節點,將這兩個節點間路徑上的所有節點權值 含這兩個節點 增加乙個給定的值。修改子樹權值 給定乙...
樹鏈剖分換根
描述 給定一棵 n 個節點的樹,初始時該樹的根為 1 號節點,每個節點有乙個給定的權值。下面依次進行 m 個操作,操作分為如下五種型別 換根 將乙個指定的節點設定為樹的新根。修改路徑權值 給定兩個節點,將這兩個節點間路徑上的所有節點權值 含這兩個節點 增加乙個給定的值。修改子樹權值 給定乙個節點,將...
樹鏈剖分 模板
class match node a n struct no no aa n 4 void init void addpage int x,int y void dfs int s,int faa,int h 根節點,父節點和深度的 if max 0 son s sign void dfs2 int...