其他分享
首页 > 其他分享> > CodeForces 811E Vladik and Entertaining Flags

CodeForces 811E Vladik and Entertaining Flags

作者:互联网

洛谷传送门

CF 传送门

思路

显然线段树。每个节点存最左端的列的并查集和最右端的列的并查集,并且维护这个节点中连通块的数量。merge 时先将 \(res\) 的连通块数量设为两个子结点的连通块数量之和,然后合并左儿子最右端的列的并查集和右儿子最左端的列的并查集,如果合并成功则 \(res \gets res - 1\)。

时间复杂度 \(O(nm + nq \log m)\),空间复杂度 \(O(nm)\)。

代码

code
/*

p_b_p_b txdy
AThousandMoon txdy
AThousandSuns txdy
hxy txdy

*/

#include <bits/stdc++.h>
#define pb push_back
#define fst first
#define scd second
#define ID(x, y) ((x - 1) * m + y)

using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;

const int maxn = 100100;

int n, m, q, c[12][maxn], fa[maxn * 12];

int find(int x) {
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}

bool merge(int x, int y) {
	x = find(x);
	y = find(y);
	if (x != y) {
		fa[x] = y;
		return 1;
	} else {
		return 0;
	}
}

struct node {
	int res, l, r, L[12], R[12];
} tree[maxn << 2];

node merge(node a, node b) {
	node res;
	memset(res.L, 0, sizeof(res.L));
	memset(res.R, 0, sizeof(res.R));
	res.res = a.res + b.res;
	res.l = a.l;
	res.r = b.r;
	for (int i = 1; i <= n; ++i) {
		fa[a.L[i]] = a.L[i];
		fa[a.R[i]] = a.R[i];
		fa[b.L[i]] = b.L[i];
		fa[b.R[i]] = b.R[i];
	}
	for (int i = 1; i <= n; ++i) {
		if (c[i][a.r] == c[i][b.l]) {
			res.res -= merge(a.R[i], b.L[i]);
		}
	}
	for (int i = 1; i <= n; ++i) {
		res.L[i] = find(a.L[i]);
		res.R[i] = find(b.R[i]);
	}
	return res;
}

void pushup(int x) {
	tree[x] = merge(tree[x << 1], tree[x << 1 | 1]);
}

void build(int rt, int l, int r) {
	if (l == r) {
		tree[rt].l = tree[rt].r = l;
		tree[rt].res = 1;
		memset(tree[rt].L, 0, sizeof(tree[rt].L));
		memset(tree[rt].R, 0, sizeof(tree[rt].R));
		tree[rt].L[1] = tree[rt].R[1] = ID(1, l);
		for (int i = 2; i <= n; ++i) {
			if (c[i][l] == c[i - 1][l]) {
				tree[rt].L[i] = tree[rt].R[i] = tree[rt].L[i - 1];
			} else {
				++tree[rt].res;
				tree[rt].L[i] = tree[rt].R[i] = ID(i, l);
			}
		}
		return;
	}
	int mid = (l + r) >> 1;
	build(rt << 1, l, mid);
	build(rt << 1 | 1, mid + 1, r);
	pushup(rt);
}

node query(int rt, int l, int r, int ql, int qr) {
	if (ql <= l && r <= qr) {
		return tree[rt];
	}
	int mid = (l + r) >> 1;
	if (qr <= mid) {
		return query(rt << 1, l, mid, ql, qr);
	} else if (ql > mid) {
		return query(rt << 1 | 1, mid + 1, r, ql, qr);
	} else {
		return merge(query(rt << 1, l, mid, ql, qr), query(rt << 1 | 1, mid + 1, r, ql, qr));
	}
}

void solve() {
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			scanf("%d", &c[i][j]);
		}
	}
	build(1, 1, m);
	while (q--) {
		int l, r;
		scanf("%d%d", &l, &r);
		printf("%d\n", query(1, 1, m, l, r).res);
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:return,int,res,查集,fa,Flags,Entertaining,find,Vladik
来源: https://www.cnblogs.com/zltzlt-blog/p/16440034.html