很神仙的题
https://www.luogu.com.cn/problem/P2486
大致如下图,我感觉本质还是数据结构线段树。
#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> #include<vector> using namespace std; const int maxn = 1e5 + 70; #define L (node<<1) #define R (node<<1|1) int n, m; int head[maxn]; int cnn = 0; struct no { int to; int next; }G[maxn * 2]; void add(int be, int en) { G[++cnn].to = en; G[cnn].next = head[be]; head[be] = cnn; } int f[maxn], siz[maxn], son[maxn], dep[maxn], Lc, Rc; int id[maxn], top[maxn]; int dfs1(int x, int fa, int d) { f[x] = fa; dep[x] = d; siz[x] = 1; int s = 0; for (int i = head[x]; i; i = G[i].next) { int p = G[i].to; if (p == fa) continue; dfs1(p, x, d + 1); siz[x] += siz[p]; if (siz[p] > s) { s = siz[p]; son[x] = p; } } return 0; } int cn = 0; int dfs2(int x, int c) { id[x] = ++cn; top[x] = c; if (son[x]) dfs2(son[x], c); for (int i = head[x]; i; i = G[i].next) { int p = G[i].to; if (p == f[x] || p == son[x]) continue; dfs2(p, p); } return 0; } int list[maxn]; struct Node { int l, r; int lc, rc; int flag, num; }tree[1000000]; void push_up(int node) { int l = node * 2; int r = node * 2 + 1; tree[node].num = tree[l].num + tree[r].num; if (tree[l].rc == tree[r].lc) tree[node].num--; tree[node].lc = tree[l].lc; tree[node].rc = tree[r].rc; } void push(int node,int clor) { tree[node].lc = tree[node].rc = clor; tree[node].flag = 1; tree[node].num = 1; } void push_down(int node) { int l = node * 2; int r = node * 2 + 1; if (tree[node].flag) { tree[node].flag = 0; tree[l].flag = tree[r].flag = 1; tree[l].num = tree[r].num = 1; tree[l].lc = tree[l].rc = tree[node].lc; tree[r].lc = tree[r].rc = tree[node].rc; } return; } void bulit(int node, int be, int en){ tree[node].l = be; tree[node].r = en; if (be == en) { return; } int mid = (be + en) / 2; bulit(L, be, mid); bulit(R, mid + 1, en); } int update(int node, int LL, int RR, int val) { int l = node * 2; int r = node * 2 + 1; if (LL <= tree[node].l && tree[node].r <= RR) { push(node, val); return 0; } int mid = (tree[node].l + tree[node].r) / 2; push_down(node); if (LL <= mid) update(l,LL, RR, val); if (RR > mid) update(r, LL, RR, val); push_up(node); } int qurry(int node, int LL, int RR) { int l = node * 2; int r = node * 2 + 1; int mid = (tree[node].l + tree[node].r) / 2; if (LL <= tree[node].l && tree[node].r <= RR) { if (LL == tree[node].l) Lc = tree[node].lc; if (RR == tree[node].r) Rc = tree[node].rc; return tree[node].num; } push_down(node); if (RR <= mid) { return qurry(l, LL, RR); } else if (LL > mid) { return qurry(r, LL, RR); } else { int ans = qurry(l, LL, RR) + qurry(r, LL, RR); if (tree[l].rc == tree[r].lc) ans--; return ans; } } int upadd(int x, int y, int val) { while (top[x]!= top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); update(1, id[top[x]], id[x], val); x = f[top[x]]; } if (dep[x] > dep[y]) swap(x, y); update(1, id[x], id[y], val); return 0; } int ask(int x, int y) { int ans1 = 0; int ans2 = 0; int ans = 0; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) { swap(x, y); swap(ans1, ans2); } ans += qurry(1, id[top[x]], id[x]); if (Rc == ans1) ans--; x = f[top[x]]; ans1 = Lc; } if (dep[x] > dep[y]) { swap(x, y); swap(ans1, ans2); } ans += qurry(1, id[x], id[y]); if (Lc == ans1) ans--; if (Rc == ans2) ans--; return ans; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &list[i]); } int be, en; for (int i = 0; i < n - 1; i++) { scanf("%d%d", &be, &en); add(be, en); add(en, be); } dfs1(1, -1, 0); dfs2(1, 1); bulit(1, 1, n); for (int i = 1; i <= n; i++) { update(1, id[i], id[i], list[i]); } int val; while (m--) { char s[10]; scanf("%s", s); if (s[0] == 'Q') { int x, y; scanf("%d %d", &x, &y); printf("%d ", ask(x, y)); } else { scanf("%d %d %d", &be, &en, &val); upadd(be, en, val); } } return 0; }