【省內訓練2018-10-26】矩陣
阿新 • • 發佈:2018-11-19
【思路要點】
- 用十字連結串列維護整個矩陣,操作時將被操作的子矩形提取出來,改變周圍一圈點的連邊,再拼接回去即可,單次操作修改的邊數是 的。
- 具體而言,一種可行的實現方式是在矩形周圍增設一圈點作為哨兵節點,這些節點將不能被修改,用於提取子矩形。每個點記錄其左右兩個點的集合 和上下兩個點的集合 ,在翻轉時,一箇中間點的 和 可能會互換,但集合 是不變的。
- 這樣的儲存方式在想要訪問 的時候需要同時知道 和 , 即為集合 中不是 的一個元素,這也是為什麼我們需要一圈哨兵節點來提取子矩形的原因。
- 時間複雜度 。
【程式碼】
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e3 + 5; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } struct info {int l, r, u, d; }; int n, m, q, tot, b[MAXN][MAXN], tmp[MAXN][MAXN], old[MAXN][MAXN]; int from[MAXN * MAXN], to[MAXN * MAXN]; info a[MAXN * MAXN]; void getr(int pos, int r) { if (pos == 0 || pos == n + 1) { for (int i = 1; i <= m; i++) tmp[pos][i] = old[pos][i] = b[pos][i]; return; } for (int i = 0, now = b[pos][0], last = 0; i <= r; i++) { tmp[pos][i] = old[pos][i] = now; int dest; if (a[now].r == last) dest = a[now].l; else dest = a[now].r; last = now, now = dest; } } void getc(int pos, int r) { if (pos == 0 || pos == m + 1) { for (int i = 1; i <= n; i++) tmp[i][pos] = old[i][pos] = b[i][pos]; return; } for (int i = 0, now = b[0][pos], last = 0; i <= r; i++) { tmp[i][pos] = old[i][pos] = now; int dest; if (a[now].d == last) dest = a[now].u; else dest = a[now].d; last = now, now = dest; } } void access(int xl, int yl, int xr, int yr) { getr(xl - 1, yr), getr(xl, yr); getr(xr + 1, yr), getr(xr, yr); getc(yl - 1, xr), getc(yl, xr); getc(yr + 1, xr), getc(yr, xr); } void modify(int pos, int from, int to) { a[pos].u = ((a[pos].u == from) ? (to) : (a[pos].u)); a[pos].d = ((a[pos].d == from) ? (to) : (a[pos].d)); a[pos].l = ((a[pos].l == from) ? (to) : (a[pos].l)); a[pos].r = ((a[pos].r == from) ? (to) : (a[pos].r)); } void makeup(int xl, int yl, int xr, int yr) { for (int i = xl; i <= xr; i++) { modify(tmp[i][yl - 1], from[tmp[i][yl - 1]], to[tmp[i][yl - 1]]); modify(tmp[i][yr + 1], from[tmp[i][yr + 1]], to[tmp[i][yr + 1]]); } for (int i = yl; i <= yr; i++) { modify(tmp[xl - 1][i], from[tmp[xl - 1][i]], to[tmp[xl - 1][i]]); modify(tmp[xr + 1][i], from[tmp[xr + 1][i]], to[tmp[xr + 1][i]]); } for (int i = yl; i <= yr; i++) { int pos = tmp[xl][i]; if (tmp[xl][i] == tmp[xr][i]) { if (a[pos].u == tmp[xl - 1][i] && a[pos].d == tmp[xr + 1][i]) continue; if (a[pos].d == tmp[xl - 1][i] && a[pos].u == tmp[xr + 1][i]) continue; } if (a[pos].u == old[xl - 1][i]) a[pos].u = tmp[xl - 1][i]; if (a[pos].d == old[xl - 1][i]) a[pos].d = tmp[xl - 1][i]; pos = tmp[xr][i]; if (a[pos].u == old[xr + 1][i]) a[pos].u = tmp[xr + 1][i]; if (a[pos].d == old[xr + 1][i]) a[pos].d = tmp[xr + 1][i]; } for (int i = xl; i <= xr; i++) { int pos = tmp[i][yl]; if (tmp[i][yl] == tmp[i][yr]) { if (a[pos].l == tmp[i][yl - 1] && a[pos].r == tmp[i][yr + 1]) continue; if (a[pos].r == tmp[i][yl - 1] && a[pos].l == tmp[i][yr + 1]) continue; } if (a[pos].l == old[i][yl - 1]) a[pos].l = tmp[i][yl - 1]; if (a[pos].r == old[i][yl - 1]) a[pos].r = tmp[i][yl - 1]; pos = tmp[i][yr]; if (a[pos].l == old[i][yr + 1]) a[pos].l = tmp[i][yr + 1]; if (a[pos].r == old[i][yr + 1]) a[pos].r = tmp[i][yr + 1]; } } int main() { read(n), read(m), read(q); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) b[i][j] = ++tot; for (int i = 1; i <= n; i++) { b[i][0] = ++tot; a[tot].r = b[i][1]; b[i][m + 1] = ++tot; a[tot].l = b[i][m]; } for (int i = 1; i <= m; i++) { b[0][i] = ++tot; a[tot].d = b[1][i]; b[n + 1][i] = ++tot; a[tot].u = b[n][i]; } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) a[b[i][j]] = (info) {b[i][j - 1], b[i][j + 1], b[i - 1][j], b[i + 1][j]}; while (q--) { char opt = getchar(); while (opt != 'H' && opt != 'V') opt = getchar(); int xl, yl, xr, yr; read(xl), read(yl), read(xr), read(yr); access(xl, yl, xr, yr); for (int i = xl; i <= xr; i++) { from[tmp[i][yl - 1]] = tmp[i][yl]; from[tmp[i][yr + 1]] = tmp[i][yr]; } for (int i = yl; i <= yr; i++) { from[tmp[xl - 1][i]] = tmp[xl][i]; from[tmp[xr + 1][i]] = tmp[xr][i]; } if (opt == 'H') { for (int i = yl, j = yr; i <= j; i++, j--) { swap(tmp[xl - 1][i], tmp[xl - 1][j]); swap(tmp[xr + 1][i], tmp[xr + 1][j]); } for (int i = xl; i <= xr; i++) swap(tmp[i][yl - 1], tmp[i][yr + 1]); } else { for (int i = xl, j = xr; i <= j; i++, j--) { swap(tmp[i][yl - 1], tmp[j][yl - 1]); swap(tmp[i][yr + 1], tmp[j][yr + 1]); } for (int i = yl; i <= yr; i++) swap(tmp[xl - 1][i], tmp[xr + 1][i]); } for (int i = xl; i <= xr; i++) { to[tmp[i][yl - 1]] = tmp[i][yl]; to[tmp[i][yr + 1]] = tmp[i][yr]; } for (int i = yl; i <= yr; i++) { to[tmp[xl - 1][i]] = tmp[xl][i]; to[tmp[xr + 1][i]] = tmp[xr][i]; } makeup(xl, yl, xr, yr); } for (int i = 1; i <= n; i++) getr(i, m); for (int i = 1; i <= n; i++) { ll ans = 0; for (int j = 1; j <= m; j++) ans += tmp[i][j]; printf("%lld ", ans); } printf("\n"); for (int j = 1; j <= m; j++) { ll ans = 0; for (int i = 1; i <= n; i++) ans += tmp[i][j]; printf("%lld ", ans); } printf("\n"); return 0; }