2020.10.6 提高組模擬
阿新 • • 發佈:2020-10-09
2020.10.6 提高組模擬
6815. 【2020.10.06提高組模擬】樹的重心
Description
給定 \(n \times m\) 的矩陣,\((i, j)\) 的顏色為 \(s_{i,j}\),
q 次操作,每次將 \((1, 1)\) 所在的連通塊顏色替換,求每次替換後連通塊的大小。
連通塊:若 \((x, y)\),\((x', y;)\) 存在公共邊且顏色相同則在同一連通塊內。
Data Constraint
\(1 \leq n, m \leq 1000\),\(1 \leq 顏色種類數 \leq 10^6\),運算元小於等於 \(2 \times 10^5\)
Solution
只需要維護與 \((1, 1)\)
每次操作將與替換顏色相同的點所在的連通塊加入答案,
並把連通塊周圍未加入佇列的點加入佇列。
提前將處理出連通塊也許可以簡化操作。
Code
#include <cstdio> #include <cstring> #include <algorithm> #include <bitset> using namespace std; #define N 1001 #define M 1000001 #define fo(i, x, y) for(int i = x; i <= y; i ++) #define Fo(i, x, q) for(int i = x; i; i = q[i].next) struct NEXT_P { int x, next; } p1[M + 1], p2[M << 2]; struct Arr { int x, y, f, siz; } fa[M << 1]; int h1[M << 1], h2[M + 1], c[N + 1][N + 1], a[N + 1][N + 1]; bitset <M << 1> used, vis; int n, m, q, k, cnt1 = 0, cnt2 = 0, tot = 0, ans = 0; void read(int &x) { char ch = getchar(); x = 0; while (ch < '0' || ch > '9') ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + ch - 48, ch = getchar(); } int Getfa(int x) { return x == fa[x].f ? x : fa[x].f = Getfa(fa[x].f); } void Merge(int u, int v) { int x = Getfa(u), y = Getfa(v); if (x == y) return; fa[y].siz += fa[x].siz; fa[x].f = fa[y].f; } void Add2(int u, int v) { p2[ ++ cnt2 ] = (NEXT_P) { v, h2[u] }, h2[u] = cnt2; } void Link(int u, int v) { Add2(u, v), Add2(v, u); } void Add1(int col, int v) { p1[ ++ cnt1 ] = (NEXT_P) { v, h1[col] }, h1[col] = cnt1; } int test1 = 0, test2 = 0; void Solve(int col) { Fo(i, h1[col], p1) if (! used[p1[i].x]) { used[p1[i].x] = 1, h1[col] = p1[i].next; ans += fa[p1[i].x].siz; Fo(j, h2[p1[i].x], p2) if (! vis[p2[j].x]) Add1(c[fa[p2[j].x].x][fa[p2[j].x].y], p2[j].x), vis[p2[j].x] = 1; } } int main() { freopen("color.in", "r", stdin); freopen("color.out", "w", stdout); read(n), read(m), read(q), read(k); fo(i, 1, n) fo(j, 1, m) read(c[i][j]); fo(i, 1, n) fo(j, 1, m) fa[ a[i][j] = ++ tot ] = (Arr) { i, j, tot, 1 }; fo(i, 1, n) fo(j, 1, m) { if (i > 1 && c[i - 1][j] == c[i][j]) Merge(a[i][j], a[i - 1][j]); if (j > 1 && c[i][j - 1] == c[i][j]) Merge(a[i][j], a[i][j - 1]); } fo(i, 1, n) fo(j, 1, m) { if (i > 1 && c[i - 1][j] != c[i][j]) Link(Getfa(a[i - 1][j]), Getfa(a[i][j])); if (j > 1 && c[i][j - 1] != c[i][j]) Link(Getfa(a[i][j - 1]), Getfa(a[i][j])); } used.reset(), vis.reset(); Add1(c[1][1], Getfa(a[1][1])); vis[Getfa(a[1][1])] = 1; Solve(c[1][1]); int x; fo(OPT, 1, q) { read(x); Solve(x); printf("%d\n", ans); } return 0; }
6815.【2020.10.06提高組模擬】樹的重心
Description & Solution
6816. 【2020.10.06提高組模擬】隨機的排列
暫時還不會...