2590 树的统计
Posted zw130-lzr-blogs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2590 树的统计相关的知识,希望对你有一定的参考价值。
看到lct的题解比较少,所以我来贡献一篇
注意的地方and坑点
1. 只用把mmax [ 0 ](维护的最大值)初始化为极小值
2. sum [ i ] , mmax [ i ]在输入时就可赋值为val [ i ]
3. 要先储存下联通的点,在输入完val后再进行link操作
CHANGE操作
change ( x , v )表示把 val [ x ] 改成v
步骤:
1. 将x点splay到根
2. 更新 val [ x ] = v
3. 进行pushup(x)操作
QMAX and QSUM操作
输入x,y表示询问x,y路径上的最大权值或者路径和
步骤
1. 只需split ( x , y ),然后输出 mmax [ y ] 或者 sum [ y ] 即可
2. 此时 mmax [ y ] 或 sum [ y ] 表示的就是x到y这条链上的最大权值 或者 权值和了
#include <iostream> #include <cmath> #include <cstring> #include <cstdio> #include <algorithm> #define MN 4000001 #define re register int #define ll long long #define inf 0x7fffffff using namespace std; int f[MN], val[MN], sum[MN], r[MN], son[MN][2]; int mmax[MN], size[MN]; int fake1[MN], fake2[MN]; int zhan[MN]; int n, m, cnt; int get(int x) ////判断节点是否为一个Splay的根(与普通Splay的区别1) return son[f[x]][0] == x || son[f[x]][1] == x; ////如果连的是轻边,他的父亲的儿子里没有它 void pushup(int x) sum[x] = sum[son[x][0]] + sum[son[x][1]] + val[x]; mmax[x] = max(max(mmax[son[x][0]], mmax[son[x][1]]), val[x]); void filp(int x) swap(son[x][0], son[x][1]); r[x] ^= 1; void pushdown(int x) if (!r[x]) return; r[x] = 0; if (son[x][0]) filp(son[x][0]); if (son[x][1]) filp(son[x][1]); void rotate(int x) int y = f[x], z = f[y], k = (son[y][1] == x), s = son[x][!k]; if (get(y)) son[z][son[z][1] == y] = x; son[x][!k] = y; son[y][k] = s; if (s) f[s] = y; f[y] = x; f[x] = z; pushup(y); // pushup(x); void splay(int x) int y = x, top = 0; zhan[++top] = y; while (get(y)) zhan[++top] = f[y], y = f[y]; while (top) pushdown(zhan[top--]); while (get(x)) y = f[x], top = f[y]; if (get(y)) rotate((son[y][0] == x) ^ (son[top][0] == y) ? x : y); rotate(x); pushup(x); return; void access(int x) for (re y = 0; x; y = x, x = f[x]) splay(x); son[x][1] = y; pushup(x); void makeroot(int x) access(x); splay(x); filp(x); int findroot(int x) access(x); splay(x); while (son[x][0]) pushdown(x), x = son[x][0]; splay(x); return x; void split(int x, int y) makeroot(x); access(y); splay(y); void cut(int x, int y) split(x, y); if (findroot(y) == x && f[y] == x && !son[y][0]) f[y] = son[x][1] = 0; pushup(x); return; void link(int x, int y) makeroot(x); if (findroot(y) != x) f[x] = y; void change(int x, int v) splay(x); val[x] = v; pushup(x); int main() mmax[0] = -inf; scanf("%d", &n); for (re i = 1; i <= n - 1; i++) scanf("%d%d", &fake1[i], &fake2[i]); //先储存下要link的点,等输入完val后再操作 //巨坑 for (re i = 1; i <= n; i++) scanf("%d", &val[i]); sum[i] = mmax[i] = val[i]; int t; for (re i = 1; i <= n - 1; i++) link(fake1[i], fake2[i]); scanf("%d", &t); for (re i = 1; i <= t; i++) char s[7]; int a1, a2; scanf("%s", s); scanf("%d%d", &a1, &a2); if (s[0] == ‘C‘) change(a1, a2); if (s[0] == ‘Q‘ && s[1] == ‘M‘) split(a1, a2); printf("%d\n", mmax[a2]); if (s[0] == ‘Q‘ && s[1] == ‘S‘) split(a1, a2); printf("%d\n", sum[a2]); // for(re i=1;i<=n;i++) // printf("%d %d\n",mmax[i],sum[i]); return 0;
以上是关于2590 树的统计的主要内容,如果未能解决你的问题,请参考以下文章