题意:给一颗树,n个节点,m次操作。每次操作使u到v的路径上每个节点中颜色z的数量加1,最后询问每个节点中数量最多的颜色。
思路:显然,我们得维护每个节点中颜色的最大值。那么我们给每个节点开一颗权值线段树,维护颜数量的最大值。现在关键是如何优化路径操作 —— 树上差分。
关于树上差分的可以参考蓝书上的解释
“根据差分序列的前缀和是原序列"这一原理,在树上可以进行类似的化简,其中"区间操作"对应为"路径操作”,“前缀和"对应为"子树和”。
我们设u,v的lca为t,类似于数列上差分我们让u的z+1, v的z+1, t的z-1,t的父亲-1(存在的话)。现在前缀和的过程就相当于是合并线段树的过程。(这空间消耗也太大了…)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define lsn (u << 1)
#define rsn (u << 1 | 1)
#define mid (l + r >> 1)
const int MAXN = 1e5 + 10;
const int MAX_LEN = 1e7;
vector<int> g[MAXN];
int n, m, tot;
int tr[MAX_LEN], cnt[MAX_LEN], ans[MAXN];
int rt[MAX_LEN], ls[MAX_LEN], rs[MAX_LEN];
int dp[21][MAXN], depth[MAXN];
void pushup(int u) {
if(cnt[ls[u]] >= cnt[rs[u]]) {
cnt[u] = cnt[ls[u]]; tr[u] = tr[ls[u]];}
else {
cnt[u]