树状数组树链剖分
其实树状数组和线段树写树剖都差不多,只是换了一种储存数据的方式,一种占用空间小,但是相对耗时,一种占用空间大,但是很快。
模板题:树链剖分
用树状数组会 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;
}
CAD加油!欢迎跟我一起讨论学习算法,QQ:1401650042