[模板]树链剖分
Posted foxc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[模板]树链剖分相关的知识,希望对你有一定的参考价值。
#include<bits/stdc++.h>
#define lson(x) (x << 1)
#define rson(x) (x << 1 | 1)
using namespace std;
const int N = 100010,M = 200010;
int n,m,r,p;
long long a[N];
int d[N],son[N],fa[N],siz[N],top[N],rk[N],id[N],cnt;//树链剖分
int head[N],edge[M],nxt[M],from[M],to[M],tot;//邻接表
void add_edge(int x,int y)
from[++tot] = x;
to[tot] = y;
nxt[tot] = head[x];
head[x] = tot;
//线段树
struct Tree
int l,r;
long long sum,tag;
t[N*4];
void push_up(int x) t[x].sum = (t[lson(x)].sum + t[rson(x)].sum) % p;
void push_down(int x)
if(t[x].tag)
t[lson(x)].tag = (t[lson(x)].tag + t[x].tag) % p;
t[lson(x)].sum = (t[lson(x)].sum + t[x].tag *(t[lson(x)].r - t[lson(x)].l + 1)) % p;
t[rson(x)].tag = (t[rson(x)].tag + t[x].tag) % p;
t[rson(x)].sum = (t[rson(x)].sum + t[x].tag *(t[rson(x)].r - t[rson(x)].l + 1)) % p;
t[x].tag = 0;
void build(int x,int ll,int rr)
t[x].l = ll; t[x].r = rr;
if(ll == rr)
t[x].sum = a[rk[ll]];
if(t[x].sum > p) t[x].sum %= p;
return;
int mid = (ll + rr) >> 1;
build(lson(x),ll,mid);
build(rson(x),mid + 1,rr);
push_up(x);
void update(int x,int ll,int rr,int k)
if(ll <= t[x].l && t[x].r <= rr)
t[x].sum = (t[x].sum + k * (t[x].r - t[x].l + 1)) % p;
t[x].tag = (t[x].tag + k) % p;
return;
push_down(x);
int mid = (t[x].l + t[x].r) >> 1;
if(ll <= mid) update(lson(x),ll,rr,k);
if(mid < rr) update(rson(x),ll,rr,k);
push_up(x);
long long query(int x,int ll,int rr)
if(ll <= t[x].l && t[x].r <= rr) return t[x].sum;
int mid = (t[x].l + t[x].r) >> 1;
long long res = 0;
push_down(x);
if(ll <= mid) res = (res + query(lson(x),ll,rr)) % p;
if(mid < rr) res = (res + query(rson(x),ll,rr)) % p;
push_up(x);
return res;
//树链剖分
void dfs1(int x)
siz[x] = 1;
for(int i = head[x]; i; i = nxt[i])
if(!siz[to[i]])
d[to[i]] = d[x] + 1;
fa[to[i]] = x;
dfs1(to[i]);
siz[x] += siz[to[i]];
if(!son[x] || siz[to[i]] > siz[son[x]])
son[x] = to[i];
void dfs2(int x,int t)
top[x] = t;
id[x] = ++cnt;
rk[cnt] = x;
if(!son[x]) return;
dfs2(son[x],t);
for(int i = head[x]; i; i = nxt[i])
if(to[i] != son[x] && to[i] != fa[x])
dfs2(to[i],to[i]);
int main()
// freopen("testdata (6).in","r",stdin);
// freopen("test.txt","w",stdout);
cin >> n >> m >> r >> p;
for(int i = 1; i <= n; i++)
scanf("%lld",&a[i]);
for(int i = 1; i < n; i++)
int x,y;
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);
dfs1(r);
dfs2(r,r);
build(1,1,n);
for(int i = 1; i <= m; i++)
int op = 0,x = 0,y = 0,z = 0;
scanf("%d%d",&op,&x);
if(op == 1)
scanf("%d%d",&y,&z);
while(top[x] != top[y])
if(d[top[y]] > d[top[x]]) swap(x,y);
update(1,id[top[x]],id[x],z);
x = fa[top[x]];
if(d[x] > d[y]) swap(x,y);
update(1,id[x],id[y],z);
if(op == 2)
scanf("%d",&y);
long long ans = 0;
while(top[x] != top[y])
if(d[top[y]] > d[top[x]]) swap(x,y);
ans = (ans + query(1,id[top[x]],id[x])) % p;
x = fa[top[x]];
if(d[x] > d[y]) swap(x,y);
ans = (ans + query(1,id[x],id[y]))% p;
printf("%lld\n",ans);
if(op == 3)
scanf("%d",&z);
update(1,id[x],id[x] + siz[x] - 1,z);
if(op == 4)
printf("%lld\n",query(1,id[x],id[x] + siz[x] - 1));
return 0;
以上是关于[模板]树链剖分的主要内容,如果未能解决你的问题,请参考以下文章