luogu P4556 [Vani有约会]雨天的尾巴
题意
给定一棵树,还有若干操作
每次操作是将树上的一条路径上的每个点加上一个颜色
然后询问每个点上出现最多的颜色是哪个?
题解
sb题
直接差分完后线段树合并即可
假设一条路径 u ———》 v
就是在u, v那里分别加1
lca, fa[lca]那里分别减1
然后就没了
code:
#include<bits/stdc++.h>
#define N 1000005
using namespace std;
struct edge {
int v, nxt;
}e[N << 1];
int p[N], eid;
void init() {
memset(p, -1, sizeof p);
eid = 0;
}
void insert(int u, int v) {
e[eid].v = v;
e[eid].nxt = p[u];
p[u] = eid ++;
}
struct A {
int x, o;
};
vector<A> a[N];
int dep[N], fa[N][22], ch[N << 4][2], ma[N << 4], n, m, tot, root[N], ans[N], size[N << 4];
void dfs(int u) {
for(int i = p[u]; i + 1; i = e[i].nxt) {
int v = e[i].v;
if(v == fa[u][0]) continue;
fa[v][0] = u;
dep[v] = dep[u] + 1;
dfs(v);
}
}
int LCA(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = 19; i >= 0; i --) if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
if(x == y) return x;
for(int i = 19; i >= 0; i --) if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
void update(int rt) {
ma[rt] = max(ma[ch[rt][0]], ma[ch[rt][1]]);
}
void insert(int &rt, int l, int r, int x, int o) {
if(!rt) rt = ++ tot;
if(l == r) {
ma[rt] += o;
return;
}
int mid = (l + r) >> 1;
if(x <= mid) insert(ch[rt][0], l, mid, x, o);
else insert(ch[rt][1], mid + 1, r, x, o);
update(rt);
}
int find(int rt, int l, int r, int o) {
if(l == r) return l;
int mid = (l + r) >> 1;
if(ma[ch[rt][0]] == o) return find(ch[rt][0], l, mid, o);
else return find(ch[rt][1], mid + 1, r, o);
}
int merge(int x, int y, int l, int r) {
if(!x && !y) return 0;
if(!x) return y;
if(!y) return x;
if(l == r) {
ma[x] += ma[y];
return x;
}
int mid = (l + r) >> 1;
ch[x][0] = merge(ch[x][0], ch[y][0], l, mid);
ch[x][1] = merge(ch[x][1], ch[y][1], mid + 1, r);
update(x);
return x;
}
void dfss(int u) {
for(int i = 0; i < a[u].size(); i ++) {
insert(root[u], 0, 100000, a[u][i].x, a[u][i].o);
}
for(int i = p[u]; i + 1; i = e[i].nxt) {
int v = e[i].v;
if(v == fa[u][0]) continue;
dfss(v);
root[u] = merge(root[u], root[v], 0, 100000);
}
ans[u] = find(root[u], 0, 100000, ma[root[u]]);
}
int main() {
init();
scanf("%d%d", &n, &m);
for(int i = 1; i < n; i ++) {
int u, v;
scanf("%d%d", &u, &v);
insert(u, v);
insert(v, u);
}
dep[1] = 1;
dfs(1);
for(int j = 1; j <= 19; j ++)
for(int i = 1; i <= n; i ++)
fa[i][j] = fa[fa[i][j - 1]][j - 1];
for(int i = 1; i <= m; i ++) {
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
int lca = LCA(u, v);
a[u].push_back(A{c, 1});
a[v].push_back(A{c, 1});
a[lca].push_back(A{c, -1});
a[fa[lca][0]].push_back(A{c, -1});
}
dfss(1);
for(int i = 1; i <= n; i ++) printf("%d\n", ans[i]);
return 0;
}
坑点
不给救济粮QWQ
线段树merge 一定要return!!!