[SDOI2011]染色
很神仙的题
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\n", ask(x, y));
}
else {
scanf("%d %d %d", &be, &en, &val);
upadd(be, en, val);
}
}
return 0;
}
寻找真正的热爱

浙公网安备 33010602011771号