CodeForces 811E Vladik and Entertaining Flags
思路
显然线段树。每个节点存最左端的列的并查集和最右端的列的并查集,并且维护这个节点中连通块的数量。merge
时先将 的连通块数量设为两个子结点的连通块数量之和,然后合并左儿子最右端的列的并查集和右儿子最左端的列的并查集,如果合并成功则 。
时间复杂度 ,空间复杂度 。
代码
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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?