如題,已知一棵包含n個結點的樹(連通且無環),每個節點上包含乙個數值,需要支援以下操作:
操作1:1 x y z 表示將樹從x到y結點最短路徑上所有節點的值都加上z
操作2:2 x y 表示求樹從x到y結點最短路徑上所有節點的值之和
操作3:3 x z 表示將以x為根節點的子樹內所有節點值都加上z
操作4:4 x 表示求以x為根節點的子樹內所有節點值之和
#include #include #define ci const int
const int maxn = 100010;
typedef long long ll;
int n, m, r, mod, cnt1, cnt2, cnt3, u, v, opt, x, y, z;
int h[maxn], to[maxn << 1], nxt[maxn << 1];
int va[maxn], w[maxn], fa[maxn], hvs[maxn], dep[maxn], sz[maxn], id[maxn], top[maxn];
char ch;
void _add(int& x, const int k)
inline void add_edge(ci& u, ci& v)
void dfs1(ci& u)
}void dfs2(ci& u, ci& tp)
struct segment_tree
void push_down(ci& x, ci& len)
void build(ci& x, ci& l, ci& r)
int mid = (l + r) >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
push_up(x);
}void add(ci& x, ci& l, ci& r, ci& l1, ci& r1, ci& k)
if (la[x]) push_down(x, r - l + 1);
int mid = (l + r) >> 1;
if (l1 <= mid) add(x << 1, l, mid, l1, r1, k);
if (r1 > mid) add(x << 1 | 1, mid + 1, r, l1, r1, k);
push_up(x);
}int query(ci& x, ci& l, ci& r, ci& l1, ci& r1, int ans = 0)
}seg;
inline void add1(int x, int y, ci& z)
if (dep[x] > dep[y]) std::swap(x, y);
seg.add(1, 1, n, id[x], id[y], z);
}inline int query1(int x, int y, int s = 0)
if (dep[x] > dep[y]) std::swap(x, y);
_add(s, seg.query(1, 1, n, id[x], id[y]));
return s;
}inline void add2(ci& x, ci& z)
inline int query2(ci& x)
int main()
fa[r] = r; dfs1(r); dfs2(r, r); seg.build(1, 1, n);
for (register int i = 1; i <= m; ++i)
else if (opt == 2)
else if (opt == 3)
else
}}
樹鏈剖分 模板
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...
模板 樹鏈剖分
define maxn 50010 define l u u 1 define r u u 1 1 寫在類裡面爆棧 int n,m,q int tim 時間戳 int num maxn 樹上每個節點的初始值 int siz maxn siz u 表示以u為根的子樹的節點數 int top maxn ...
樹鏈剖分模板
點權模板 1 m a b c將節點a到節點b路徑上所有點都染成顏色c 2 q a b詢問節點a到節點b路徑上的顏色段數量 連續相同顏色被認為是同一段 如 112221 由3段組成 11 222 和 1 const int n 100100 struct edge g n 2 int cnt,head...