BZOJ 2243 [SDOI2011]染色

2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 9961  Solved: 3778
[Submit][Status][Discuss]

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<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

总结:树剖 + 线段树维护, 注意线段树合并的时候需要判断颜色是否相同,颜色相同要减一
#include<bits/stdc++.h>

using namespace std;
const int maxn = 400005;

int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = x * 10 + ch - 48; ch = getchar();}
	return x * f;
}

int n, m, top[maxn], dep[maxn], f[maxn], siz[maxn], a[maxn], sum[maxn], rc[maxn], laz[maxn];
int head[maxn], cnt = 1, son[maxn], wt[maxn], tot = 0, id[maxn], lc[maxn]; char Q[2];
struct Node{
	int v, nxt;
} G[maxn];

void insert(int u, int v) {
	G[cnt] = (Node) {v, head[u]}; head[u] = cnt++;
}
void dfs1(int x, int fa, int deep) {
	dep[x] = deep; f[x] = fa; int maxson = -1;
	siz[x] = 1;
	for (int i = head[x]; i; i = G[i].nxt) {
		int v = G[i].v;
		if(v == fa) continue;
		dfs1(v, x, deep + 1);
		siz[x] += siz[v];
		if(siz[v] > maxson) maxson = siz[v], son[x] = v;
	}
}
void dfs2(int x, int topf) {
	id[x] = ++tot; wt[tot] = a[x]; top[x] = topf; 
	if(son[x] != 0) dfs2(son[x], topf);
	for (int i = head[x]; i; i = G[i].nxt) {
		int v = G[i].v;
		if(v == son[x] || v == f[x]) continue;
		dfs2(v, v);
	}
}
void update(int o, int l, int r) {
    sum[o] = sum[o << 1] + sum[o << 1 | 1] - (rc[o << 1] == lc[o << 1 | 1]);
	lc[o] = lc[o << 1], rc[o] = rc[o << 1 | 1]; 
}
void build(int o, int l, int r) {
	if(l == r) {
		sum[o] = 1; 
		lc[o] = rc[o] = wt[l]; return;
	} int mid = (l + r) >> 1;
	build(o << 1, l, mid); 
	build(o << 1 | 1, mid + 1, r);
	update(o, l, r);
}
void pushdown(int o, int l, int r) {
	if(laz[o]) {
		laz[o << 1] = laz[o << 1 | 1] = laz[o];
		sum[o << 1] = sum[o << 1 | 1] = 1;
		lc[o << 1] = lc[o << 1 | 1] = rc[o << 1] = rc[o << 1 | 1] = laz[o];
		laz[o] = 0;
	}
}
int query(int o, int l, int r, int ql, int qr) {
	if(r < ql || l > qr) return 0;
	if(ql <= l && r <= qr) return sum[o];
	int mid = (l + r) >> 1;
	pushdown(o, l, r);
	int res1 = query(o << 1, l, mid, ql, qr);
	int res2 = query(o << 1 | 1, mid + 1, r, ql, qr);
	if(res1 && res2) return res1 + res2 - (lc[o << 1 | 1] == rc[o << 1]);
    else return res1 + res2;
}
int getcol(int o, int l, int r, int x) {
	if(l == r) return lc[o];
	int mid = (l + r) >> 1;
	pushdown(o, l, r);
	if(x <= mid) return getcol(o << 1, l, mid, x);
	else return getcol(o << 1 | 1, mid + 1, r, x);
}
int query_rg(int x, int y) {
	int res = 0;
	while(top[x] != top[y]) {
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		res += query(1, 1, n, id[top[x]], id[x]); 
		if(getcol(1, 1, n, id[f[top[x]]]) == getcol(1, 1, n, id[top[x]])) res--;
		x = f[top[x]];
	} if(dep[x] < dep[y]) swap(x, y);
	res += query(1, 1, n, id[y], id[x]);
	return res;
}
void modify(int o, int l, int r, int ql, int qr, int z) {
	if(ql <= l && r <= qr) {
		laz[o] = z; sum[o] = 1; lc[o] = rc[o] = z; return;
	} int mid = (l + r) >> 1;
	pushdown(o, l, r);
	if(ql <= mid) modify(o << 1, l, mid, ql, qr, z);
	if(qr > mid) modify(o << 1 | 1, mid + 1, r, ql, qr, z);
	update(o, l, r);
}
void modify_rg(int x, int y, int z) {
	while(top[x] != top[y]) {
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		modify(1, 1, n, id[top[x]], id[x], z);
		x = f[top[x]];
	} if(dep[x] < dep[y]) swap(x, y);
	modify(1, 1, n, id[y], id[x], z);
}
int main() {
	n = read(); m = read();
	for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
	for (int i = 1; i <= n - 1; ++i) {
		int x, y; x = read(); y = read(); 
		insert(x, y); insert(y, x);
	} dfs1(1, -1, 0); dfs2(1, 1);
	build(1, 1, n);
	while(m--) {
		int a, b, c;
		scanf("%s", Q);
		if(Q[0] == 'Q') a = read(), b = read(), printf("%d\n", query_rg(a, b));
		else a = read(), b = read(), c = read(), modify_rg(a, b, c);
	}
}

  

 

猜你喜欢

转载自www.cnblogs.com/oi-forever/p/9066127.html