洛谷p3384 【模板】樹鏈剖分錯誤記錄node
首先感謝\(lfd\)在課上調了出來\(Orz\)ios
\(1\).之後少寫全局變量git
\(2\).線段樹遞歸的時候最好把左右區間一塊兒傳數組
\(3\).寫\(dfs\)的時候不要寫錯名字函數
\(4\).使用線段樹的操做的時候纔要用到\(dfs\)序ui
\(5\).須要開一個數組來記錄在\(dfs\)序下的節點是什麼也方便線段樹的賦值spa
\(6\).注意\(down\)函數內怎樣更新code
\(7\).在查詢的時候並不須要向上更新遞歸
因爲\(yxj\)看了\(lfd\)敲的樹鏈剖分感受壓完行以後很是的好看,由此\(yxj\)也踏上了瘋狂壓行的不歸路ci
Code:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define lson k << 1 #define rson k << 1 | 1 using namespace std; const int N = 1e5+7; int n, m, R, p, dfn[N], top[N], son[N], dep[N], fa[N], siz[N], tot, head[N << 1], cnt, num, x, y, z, w[N], l, r, ans, pre[N]; struct node {int l, r, f, w;}tr[N << 2]; struct Node {int nxt, to;}e[N << 1]; int read() { int s = 0, w = 1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') w = -1; ch = getchar();} while(isdigit(ch)) {s = s * 10 + ch - '0'; ch = getchar();} return s * w; } void build(int k, int l, int r) { tr[k].l = l, tr[k].r = r; if(l == r) {tr[k].w = w[pre[l]]; return;} int mid = (l + r) >> 1; build(lson, l, mid); build(rson, mid + 1, r); tr[k].w = (tr[lson].w + tr[rson].w) % p; } void add(int x, int y) { e[++cnt].nxt = head[x]; e[cnt].to = y; head[x] = cnt; } void dfs(int x) { siz[x] = 1; dep[x] = dep[fa[x]] + 1; for(int i = head[x]; i; i = e[i].nxt) { if(e[i].to == fa[x]) continue; fa[e[i].to] = x, dfs(e[i].to), siz[x] += siz[e[i].to]; if(siz[e[i].to] > siz[son[x]]) son[x] = e[i].to; } } void dfs1(int x) { dfn[x] = ++tot; pre[tot] = x; if(!top[x]) top[x] = x; if(son[x]) top[son[x]] = top[x], dfs1(son[x]); for(int i = head[x]; i; i = e[i].nxt) if(e[i].to != fa[x] && e[i].to != son[x]) dfs1(e[i].to); } void down(int k) { tr[lson].f += tr[k].f; tr[rson].f += tr[k].f; tr[lson].w += (tr[lson].r - tr[lson].l + 1) * tr[k].f; tr[rson].w += (tr[rson].r - tr[rson].l + 1) * tr[k].f; tr[k].f = 0; } void change_query(int k) { if(tr[k].l >= l && tr[k].r <= r) {tr[k].w += (tr[k].r - tr[k].l + 1) * z;tr[k].f += z; return;} if(tr[k].f) down(k); int mid = (tr[k].l + tr[k].r) >> 1; if(l <= mid) change_query(lson); if(r > mid) change_query(rson); tr[k].w = (tr[lson].w + tr[rson].w) % p; } void work(int x, int y) { z %= p; while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x, y); l = dfn[top[x]], r = dfn[x], change_query(1); x = fa[top[x]]; } if(dep[x] > dep[y]) swap(x, y); l = dfn[x], r = dfn[y]; change_query(1); } void ask_query(int k) { if(tr[k].l >= l && tr[k].r <= r) {ans = (ans + tr[k].w) % p; return;} if(tr[k].f) down(k); int mid = (tr[k].l + tr[k].r) >> 1; if(l <= mid) ask_query(lson); if(r > mid) ask_query(rson); tr[k].w = (tr[lson].w + tr[rson].w) % p; } void work1(int x, int y) { while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x, y); l = dfn[top[x]], r = dfn[x]; ask_query(1); x = fa[top[x]]; } if(dep[x] > dep[y]) swap(x, y); l = dfn[x]; r = dfn[y]; ask_query(1); } int main() { n = read(), m = read(), R = read(), p = read(); for(int i = 1; i <= n; i++) w[i] = read(); for(int i = 1; i < n; i++) x = read(), y = read(), add(x, y), add(y, x); dfs(R); dfs1(R); build(1, 1, n); while(m--) { num = read(); if(num == 1) cin >> x >> y >> z, work(x, y); if(num == 2) ans = 0, cin >> x >> y, work1(x, y), cout << ans << endl; if(num == 3) cin >> x >> z, l = dfn[x], r = dfn[x] + siz[x] - 1, change_query(1); if(num == 4) ans = 0, cin >> x, l = dfn[x], r = dfn[x] + siz[x] - 1, ask_query(1), cout << ans << endl; } return 0; }
謝謝收看,祝身體健康!