再存一个板子=,=
路径累加,路径求和
子树累加,子树求和
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100010, M = N * 2, INF = 0x3f3f3f3f;
struct Node{
int l, r;
LL sum, add;
}tr[N * 4];
int h[N], e[M], ne[M], idx;
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}
int n, m, root, mod;
int w[N];
int f[N], sz[N], dep[N], son[N];
void dfs1(int u, int fa)
{
f[u] = fa;
sz[u] = 1;
dep[u] = dep[fa] + 1;
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(j == fa) continue;
dfs1(j, u);
sz[u] += sz[j];
if(sz[j] > sz[son[u]]) son[u] = j;
}
}
int top[N], id[N], rk[N], tot;
void dfs2(int u, int t)
{
top[u] = t;
id[u] = ++ tot;
rk[tot] = u;
if(son[u]) dfs2(son[u], t);
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(j == f[u] or j == son[u]) continue;
dfs2(j, j);
}
}
void pushup(int u)
{
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void build(int u, int l, int r)
{
tr[u] = {l, r};
if(l == r)
{
tr[u].sum = w[rk[l]];
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void pushdown(int u)
{
Node &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
if(root.add)
{
left.add = (left.add + root.add) % mod, left.sum = (left.sum + (LL)root.add * (left.r - left.l + 1)) % mod;
right.add = (right.add + root.add) % mod, right.sum = (right.sum + (LL)root.add * (right.r - right.l + 1)) % mod;
root.add = 0;
}
}
void modify(int u, int l, int r, int c)
{
if(tr[u].l >= l and tr[u].r <= r)
{
tr[u].sum = (tr[u].sum + (LL)c * (tr[u].r - tr[u].l + 1)) % mod;
tr[u].add = (tr[u].add + c) % mod;
}
else
{
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) modify(u << 1, l, r, c);
if(r > mid) modify(u << 1 | 1, l, r, c);
pushup(u);
}
}
int query(int u, int l, int r)
{
if(tr[u].l >= l and tr[u].r <= r) return tr[u].sum;
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
LL res = 0;
if(l <= mid) res = query(u << 1, l, r);
if(r > mid) res += query(u << 1 | 1, l, r);
return res % mod;
}
void update1(int a, int b, int c) // a, b路径上的点 += c
{
while(top[a] != top[b])
{
if(dep[top[a]] < dep[top[b]]) swap(a, b);
modify(1, id[top[a]], id[a], c);
a = f[top[a]];
}
if(dep[a] > dep[b]) swap(a, b);
modify(1, id[a], id[b], c);
}
void update2(int a, int c) // 以a为根的子树中的点 += c
{
modify(1, id[a], id[a] + sz[a] - 1, c);
}
int qsum1(int a, int b) // a, b路径上的权值和
{
LL res = 0;
while(top[a] != top[b])
{
if(dep[top[a]] < dep[top[b]]) swap(a, b);
res = (res + query(1, id[top[a]], id[a]));
a = f[top[a]];
}
if(dep[a] > dep[b]) swap(a, b);
res = (res + query(1, id[a], id[b])) % mod;
return res;
}
int qsum2(int a) // 返回以a为根的子树的权值和
{
return query(1, id[a], id[a] + sz[a] - 1);
}
int main()
{
memset(h, -1, sizeof h);
scanf("%d%d%d%d", &n, &m, &root, &mod);
for(int i = 1; i <= n; i ++) scanf("%d", &w[i]);
for(int i = 1; i < n; i ++)
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
}
dfs1(root, 0);
dfs2(root, root);
build(1, 1, n);
while(m --)
{
int op, a, b, c;
scanf("%d", &op);
if(op == 1)
{
scanf("%d%d%d", &a, &b, &c);
update1(a, b, c);
}
else if(op == 2)
{
scanf("%d%d", &a, &b);
printf("%d\n", qsum1(a, b));
}
else if(op == 3)
{
scanf("%d%d", &a, &c);
update2(a, c);
}
else
{
scanf("%d", &a);
printf("%d\n", qsum2(a));
}
}
return 0;
}
emmm 不懂就问 ,树链剖分 不能 把一些东西用struct 来存吗 , qwq 好多人 都开数组 (貌似就没有用struct的 qwq
应该是可以的8,我学的板子就是这样的感觉不错就没改了qwq
orz!%%% 滑稽大佬
%%%%%%%%%%滑稽大佬
orz。。。滑稽大佬太强辣
qwq
我都这么菜了还天天混qwq,滑稽大佬这么强还天天肝qwq。。。羞愧的逃走了