Reflection
Explicación
Consideremos cada casilla individual del cuadrante superior izquierdo y calculemos la cantidad mínima de operaciones necesarias para que esta casilla y las celdas correspondientes de los otros tres cuadrantes coincidan.
- Si hay tres casillas pintadas, pintamos la celda restante, lo que toma una operación.
- Si hay dos casillas pintadas, podemos o bien pintar las otras dos celdas o quitar la pintura de las dos celdas pintadas, lo que toma dos operaciones.
- Si hay una casilla pintada, quitamos la pintura de esa celda, lo que toma una operación.
- Por último, si las cuatro están pintadas o las cuatro no lo están, ya coinciden, así que se necesitan cero operaciones.
Sumar todas las contribuciones de cada celda nos da la cantidad mínima de operaciones necesarias para cumplir la condición de reflexión. Luego, para cada una de las actualizaciones, solo hace falta considerar el cambio de contribución de la celda actualizada y de las celdas correspondientes en los otros tres cuadrantes. La forma más simple de manejarlo es restar la contribución actual de esas cuatro celdas, actualizar la grilla y después sumar la nueva contribución.
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
int n, u;
vector<string> grid;
int contribution(int r, int c) {
// 4 symmetric cells
vector<char> cells = {grid[r][c], grid[n - r - 1][c], grid[r][n - c - 1],
grid[n - r - 1][n - c - 1]};
// Min flips to make them all equal
int painted = 0;
for (char ch : cells) {
if (ch == '#') painted++;
}
return min(painted, 4 - painted);
}
int main() {
cin >> n >> u;
grid.resize(n);
for (int i = 0; i < n; i++) { cin >> grid[i]; }
// Initial answer (only need top-left quadrant)
int ans = 0;
for (int row = 0; row < n / 2; row++) {
for (int col = 0; col < n / 2; col++) { ans += contribution(row, col); }
}
cout << ans << '\n';
for (int i = 0; i < u; i++) {
int r, c;
cin >> r >> c;
r--;
c--;
ans -= contribution(r, c); // remove old contribution
grid[r][c] = (grid[r][c] == '.') ? '#' : '.'; // toggle
ans += contribution(r, c); // add new contribution
cout << ans << '\n';
}
}n, u = map(int, input().split())
grid = [list(input()) for i in range(n)]
def contribution(r, c):
# 4 symmetric cells
cells = [
grid[r][c],
grid[n - r - 1][c],
grid[r][n - c - 1],
grid[n - r - 1][n - c - 1],
]
# Min flips to make them all equal
painted = cells.count("#")
return min(painted, 4 - painted)
# Initial answer (only need top-left quadrant)
ans = 0
for row in range(n // 2):
for column in range(n // 2):
ans += contribution(row, column)
print(ans)
for i in range(u):
r, c = map(int, input().split())
r -= 1
c -= 1
ans -= contribution(r, c) # remove old contribution
grid[r][c] = "#" if grid[r][c] == "." else "." # toggle
ans += contribution(r, c) # add new contribution
print(ans)