当前位置:网站首页>【树链剖分】模板题
【树链剖分】模板题
2022-07-27 01:36:00 【行码棋】

题目链接:
https://www.luogu.com.cn/problem/P3384
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 5, M = 2 * N;
int n, m, r, p;
int w[N];
struct Segment
{
ll add, sum;
}tr[N * 4];
int dep[N], fa[N], son[N], sz[N];
int cnt, nw[N], top[N], id[N];
int e[M], h[N], ne[M], idx;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void pushup(int u)
{
tr[u].sum = (tr[u << 1].sum + tr[u << 1 | 1].sum) % p;
}
void pushdown(int u, int l, int r)
{
int mid = (l + r) >> 1;
if(tr[u].add)
{
tr[u << 1].add += tr[u].add;
tr[u << 1].sum += 1ll * (mid - l + 1) * tr[u].add;
tr[u << 1].sum %= p;
tr[u << 1 | 1].add += tr[u].add;
tr[u << 1 | 1].sum += 1ll * (r - mid) * tr[u].add;
tr[u << 1 | 1].sum %= p;
tr[u].add = 0;
}
}
void build(int u, int l, int r)
{
if(l == r)
{
tr[u].sum = nw[l];
if(tr[u].sum > p) tr[u].sum %= p;
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void modify(int u, int l, int r, int x, int y, int d)
{
if(l >= x && r <= y)
{
tr[u].sum += 1ll * (r - l + 1) * d;
tr[u].sum %= p;
tr[u].add += d;
return;
}
pushdown(u, l, r);
int mid = (l + r) >> 1;
if(x <= mid) modify(u << 1, l, mid, x, y, d);
if(y > mid) modify(u << 1 | 1, mid + 1, r, x, y, d);
pushup(u);
}
ll query(int u, int l, int r, int x, int y)
{
if(l >= x && r <= y)
return tr[u].sum % p;
pushdown(u, l, r);
int mid = (l + r) >> 1;
ll ans = 0;
if(x <= mid) ans = query(u << 1, l, mid, x, y) % p;
if(y > mid) ans = (ans + query(u << 1 | 1, mid + 1, r, x, y)) % p;
return ans;
}
//预处理dep[],fa[],sz[],son[](重儿子节点)
void dfs1(int x, int f, int depth)//x : 当前节点, f:父亲, depth:深度
{
dep[x] = depth;
fa[x] = f;
sz[x] = 1;
int mxson = -1;
for(int i = h[x]; ~i; i = ne[i])
{
int y = e[i];
if(y == f) continue;
dfs1(y, x, depth + 1);
sz[x] += sz[y];
if(sz[y] > mxson)// 记录重儿子编号
{
son[x] = y;
mxson = sz[y];
}
}
}
// 标新序号 求id[], nw[], top[] 新id-新节点权重-链顶端
void dfs2(int x, int topf)
{
id[x] = ++cnt;
nw[cnt] = w[x];
top[x] = topf;
if(!son[x]) return;//无儿子返回
dfs2(son[x], topf);
for(int i = h[x]; ~i; i = ne[i])
{
int y = e[i];
if(y == fa[x] || y == son[x])
continue;
dfs2(y, y);
}
}
ll queryRange(int x, int y)
{
ll ans = 0;
while(top[x] != top[y])//不在同一条链上
{
if(dep[top[x]] < dep[top[y]])
swap(x, y);
ans += query(1, 1, n, id[top[x]], id[x]);
ans %= p;
x = fa[top[x]];
}
if(dep[x] > dep[y])
swap(x, y);
ans = (ans + query(1, 1, n, id[x], id[y])) % p;
return ans;
}
void modifyRange(int x, int y, int d)
{
d %= p;
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]])
swap(x, y);
modify(1, 1, n, id[top[x]], id[x], d);
x = fa[top[x]];
}
if(dep[x] > dep[y])
swap(x, y);
modify(1, 1, n, id[x], id[y], d);
}
ll querySon(int x)
{
return query(1, 1, n, id[x], id[x] + sz[x] - 1);
}
void modifySon(int x, int d)
{
modify(1, 1, n, id[x], id[x] + sz[x] - 1, d);
}
void solve()
{
cin >> n >> m >> r >> p;
for(int i = 1; i <= n; i++)
cin >> w[i];
memset(h, -1, sizeof h);
for(int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
add(u, v);
add(v, u);
}
dfs1(r, -1, 1);
dfs2(r, r);
build(1, 1, n);
while(m--)
{
int op, x, y, z;
cin >> op >> x;
if(op == 1)
{
cin >> y >> z;
modifyRange(x, y, z);
}
else if(op == 2)
{
cin >> y;
cout << queryRange(x, y) << "\n";
}
else if(op == 3)
{
cin >> z;
modifySon(x, z);
}
else
cout << querySon(x) << "\n";
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
// cin >> t;
t = 1;
while(t--)
solve();
return 0;
}
边栏推荐
猜你喜欢

“date: write error: No space left on device”解决

How many implementation postures of delay queue? Daily essential skills!

HCIP第十三天笔记

周全的照护 解析LYRIQ锐歌电池安全设计

Worthington木瓜蛋白酶解离系统解决方案

Complete source code of mall applet project (wechat applet)

An error in the fourth edition of the red book?

Yilingsi T35 FPGA drives LVDS display screen

spark学习笔记(四)——sparkcore核心编程-RDD

Graphic SQL, this is too vivid!
随机推荐
优炫数据库集群如何唯一标识一条用户SQL
How to uniquely identify a user SQL in Youxuan database cluster
IDEA 连接数据库查询数据后控制台表头中文乱码的解决方法
数据库红的表如何设计才能使性能更加优化
带你了解什么是 Web3.0
技术风向标 | 云原生技术架构成熟度模型解读
正方形数组的数目(DAY 81)
Worthington木瓜蛋白酶解离系统解决方案
注解@Autowired和@Resource的区别总结
Detailed explanation of const usage in C language
数模1232
impala 执行计划详解
Hcip 13th day notes
Jmeter分布式压测
在线问题反馈模块实战(十五):实现在线更新反馈状态功能
索引最佳实践
Attention should be paid to the first parameter of setTimeout
30 minutes to thoroughly understand the synchronized lock upgrade process
字节一面:TCP 和 UDP 可以使用同一个端口吗?
unity游戏,隐私协议最简单解决方案!仅3行代码就搞定!(转载)