bzoj2243 [SDOI2011]染色

Description

给定一棵有\(n\)个节点的无根树和\(m\)个操作,操作有\(2\)类:

  1. 将节点\(a\)到节点\(b\)路径上所有点都染成颜色\(c\)
  2. 询问节点\(a\)到节点\(b\)路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
    请你写一个程序依次完成这\(m\)个操作。

Input

第一行包含\(2\)个整数\(n\)\(m\),分别表示节点数和操作数;
第二行包含\(n\)个正整数表示\(n\)个节点的初始颜色
下面 行每行包含两个整数\(x\)\(y\),表示\(x\)\(y\)之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点\(a\)到节点\(b\)路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点\(a\)到节点\(b\)(包括\(a\)\(b\))路径上的颜色段数量。

Output

对于每个询问操作,输出一行答案。

Sample Input

6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5

Sample Output

3
1
2

HINT

\(N \leqslant 10^5\),操作数\(M \leqslant 10^5\),所有的颜色\(C\)为整数且在\([0, 10^9]\)之间。

Solution

这个题啊,不过就是14个函数、160行的重工业题吗(雾。
链剖+线段树,详见代码。
话说Azrael_Death今天写了超重工业题猪国杀,%%%orz。

#include<bits/stdc++.h>
using namespace std;

inline int read() {
	int x = 0, flag = 1; char ch = getchar();
	while (ch > '9' || ch < '0') { if (ch == '-') flag = -1; ch = getchar(); }
	while (ch <= '9' && ch >= '0') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * flag;
}
inline void write(int x) { if (x >= 10) write(x / 10); putchar(x % 10 + '0'); }

#define N 500001
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drp(i, a, b) for (int i = a; i >= b; i--)
#define fech(i, x) for (int i = 0; i < x.size(); i++)
#define ls rt << 1
#define rs ls | 1

int n;
int begCol[N];
vector<int> tr[N];
int Size[N], dep[N], fa[N][18];
int pos[N], belong[N], sz;
struct segmentTree { int l, r, s, lc, rc, tag; }seg[N];

int lca(int x, int y) {
	if (dep[x] < dep[y]) swap(x, y);
	int d = dep[x] - dep[y];
	rep(i, 0, 17) if (d & (1 << i)) x = fa[x][i];
	drp(i, 17, 0) if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
	if (x == y) return x;
	return fa[x][0];
}

void dfs1(int u, int f) {
	Size[u] = 1;
	fa[u][0] = f;
	rep(i, 1, 17) fa[u][i] = fa[fa[u][i - 1]][i - 1];
	fech(i, tr[u]) if (tr[u][i] != f) {
		int v = tr[u][i];
		dep[v] = dep[u] + 1;
		dfs1(v, u);
		Size[u] += Size[v];
	}
}

void dfs2(int u, int chain) {
	pos[u] = ++sz; belong[u] = chain;
	int k = 0;
	fech(i, tr[u]) if (fa[u][0] != tr[u][i] && Size[tr[u][i]] > Size[k]) k = tr[u][i];
	if (!k) return;
	dfs2(k, chain);
	fech(i, tr[u]) if (tr[u][i] != fa[u][0] && tr[u][i] != k) dfs2(tr[u][i], tr[u][i]);
}

void build(int l, int r, int rt) {
	seg[rt].l = l, seg[rt].r = r, seg[rt].s = 1, seg[rt].tag = -1;
	if (l == r) return;
	int mid = l + r >> 1;
	build(l, mid, ls), build(mid + 1, r, rs);
}

void pushDown(int rt) {
	int tmp = seg[rt].tag; seg[rt].tag = -1;
	if (tmp == -1 || seg[rt].l == seg[rt].r)return;
	seg[ls].s = seg[rs].s = 1;
	seg[ls].tag = seg[rs].tag = tmp;
	seg[ls].lc = seg[ls].rc = tmp;
	seg[rs].lc = seg[rs].rc = tmp;
}

void pushUp(int rt) {
	seg[rt].lc = seg[ls].lc; seg[rt].rc = seg[rs].rc;
	if (seg[ls].rc != seg[rs].lc) seg[rt].s = seg[ls].s + seg[rs].s;
	else seg[rt].s = seg[ls].s + seg[rs].s - 1;
}

void change(int x, int y, int v, int rt) {
	pushDown(rt);
	int l = seg[rt].l, r = seg[rt].r;
	if (l == x && r == y) {
		seg[rt].lc = seg[rt].rc = v; seg[rt].s = 1; seg[rt].tag = v; return;
	}
	int mid = (l + r) >> 1;
	if (mid >= y) change(x, y, v, ls);
	else if (mid<x) change(x, y, v, rs);
	else
		change(x, mid, v, ls),
		change(mid + 1, y, v, rs);
	pushUp(rt);
}

int getc(int rt, int x) {
	pushDown(rt);
	int l = seg[rt].l, r = seg[rt].r;
	if (l == r) return seg[rt].lc;
	int mid = l + r >> 1;
	if (x <= mid) return getc(ls, x);
	else return getc(rs, x);
}

int ask(int x, int y, int rt) {
	pushDown(rt);
	int l = seg[rt].l, r = seg[rt].r;
	if (l == x && r == y) return seg[rt].s;
	int mid = l + r >> 1;
	if (mid >= y) return ask(x, y, ls);
	else if (mid < x) return ask(x, y, rs);
	else {
		int tmp = 1;
		if (seg[ls].rc != seg[rs].lc) tmp = 0;
		return ask(x, mid, ls) + ask(mid + 1, y, rs) - tmp;
	}
}

int solveSum(int x, int f) {
	int sum = 0;
	while (belong[x] != belong[f]) {
		sum += ask(pos[belong[x]], pos[x], 1);
		if (getc(1, pos[belong[x]]) == getc(1, pos[fa[belong[x]][0]])) sum--;
		x = fa[belong[x]][0];
	}
	sum += ask(pos[f], pos[x], 1);
	return sum;
}

void solveChange(int x, int f, int c) {
	while (belong[x] != belong[f])
		change(pos[belong[x]], pos[x], c, 1),
		x = fa[belong[x]][0];
	change(pos[f], pos[x], c, 1);
}

int main() {
	cin >> n; int q = read();
	rep(i, 1, n) begCol[i] = read();
	rep(i, 2, n) {
		int u = read(), v = read();
		tr[u].push_back(v),	tr[v].push_back(u);
	}
	dfs1(1, 0); dfs2(1, 1);
	build(1, n, 1);
	rep(i, 1, n) change(pos[i], pos[i], begCol[i], 1);
	while (q--) {
		char op[10];
		scanf("%s", op);
		int a = read(), b = read(); int t = lca(a, b);
		if (op[0] == 'Q') write(solveSum(a, t) + solveSum(b, t) - 1), puts("");
		else {
			int c = read();
			solveChange(a, t, c), solveChange(b, t, c);
		}
	}
	return 0;
}
posted @ 2018-02-05 09:29  aziint  阅读(118)  评论(0编辑  收藏  举报
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.