其实树状数组和线段树写树剖都差不多,只是换了一种储存数据的方式,一种占用空间小,但是相对耗时,一种占用空间大,但是很快。
模板题:树链剖分
用树状数组会 tle 但是这也是一种思路
// Created by CAD on 2019/8/11. #include <bits/stdc++.h> using namespace std; using ll=long long; #define lowbit(i) (i&-i) const int maxn=1e5+5; /*树状数组*/ int c[maxn], wt[maxn], laz[maxn << 2]; ll n; ll mod; inline void Add(int x, int k) { while (x<=n) c[x]=(c[x]+k)%mod, x+=lowbit(x); } inline ll getSum(int x) { ll ans=0; while (x>0) ans=(ans+c[x])%mod, x-=lowbit(x); return ans%mod; } inline ll getsum(int l, int r, int s, int t, int p) { return (getSum(r)-getSum(l-1)+mod)%mod; } int cnt=0, head[maxn << 1]; struct edge { int to, next; } e[maxn << 1]; void add(int u, int v) { e[++cnt].to=v; e[cnt].next=head[u]; head[u]=cnt; } int dep[maxn], f[maxn], siz[maxn], son[maxn]; int top[maxn], w[maxn << 1], id[maxn], tot=0; void dfs1(int x, int fa, int deep) { dep[x]=deep, f[x]=fa, siz[x]=1; int maxson=-1; for (int i=head[x]; i; i=e[i].next) { int v=e[i].to; if (v==fa) continue; dfs1(v, x, deep+1); siz[x]+=siz[v]; if (siz[v]>maxson) maxson=siz[v], son[x]=v; } } void dfs2(int u, int topf) { id[u]=++tot; wt[tot]=w[u]; top[u]=topf; if (!son[u]) return; dfs2(son[u], topf); for (int i=head[u]; i; i=e[i].next) { int v=e[i].to; if (v==f[u] || v==son[u]) continue; dfs2(v, v); } } ll qrange(int x, int y) { int ans=0; while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x, y); ans=(ans+getsum(id[top[x]], id[x], 1, n, 1)%mod)%mod; x=f[top[x]]; } if (dep[x]>dep[y]) swap(x, y); ans=(ans+getsum(id[x], id[y], 1, n, 1)%mod)%mod; return ans; } void updrange(int x, int y, int k) { k%=mod; while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]])swap(x, y); for (register int i=id[top[x]]; i<=id[x]; ++i) Add(i, k); x=f[top[x]]; } if (dep[x]>dep[y])swap(x, y); for (int i=id[x]; i<=id[y]; ++i) Add(i, k); } ll qson(int x) { return getsum(id[x], id[x]+siz[x]-1, 1, n, 1)%mod; } void updson(int x, int k) { for (register int i=id[x]; i<=id[x]+siz[x]-1; ++i) Add(i, k); } ll m, r; int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m >> r >> mod; for (int i=1; i<=n; ++i) cin >> w[i]; for (int i=1, u, v; i<n; ++i) cin >> u >> v, add(u, v), add(v, u); dfs1(r, 0, 1); dfs2(r, r); for (int i=1; i<=n; ++i) Add(i, wt[i]); while (m--) { int k, x, y, z; cin >> k; if (k==1) cin >> x >> y >> z, updrange(x, y, z); else if (k==2) cin >> x >> y, cout << qrange(x, y) << endl; else if (k==3) cin >> x >> y, updson(x, y); else if (k==4) cin >> x, cout << qson(x) << endl; } return 0; }