CodeForces 811E Vladik and Entertaining Flags
作者:互联网
思路
显然线段树。每个节点存最左端的列的并查集和最右端的列的并查集,并且维护这个节点中连通块的数量。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