AT_arc205_a 题解

· · 题解

::::info[题目大意]{open}

洛谷题面有点问题。建议看 AtCoder 的。

就是说给你一个字符矩阵,然后 Q 个询问,每次询问限定一个矩形区域,然后你可以找一个全是 .2\times 2 的正方形,然后把其中任意一个改成 #。问你能这样操作多少次。要求 O(1)O(\log) 回答每次询问。 ::::

考虑如何算对于每个询问的答案。

我们发现每个点至多当一次矩形内的左上角。所以直接枚举这个左上角,然后看以它为左上角的 2\times 2 的正方形是不是都是 .,然后把其中任意一个改成 # 的话就直接改左上角就行了。

也就是说,我们现在要统计对于在询问的矩形内的每个 2\times 2 的正方形有多少个是全为 . 的。

二维前缀和维护即可,注意边界。

::::success[AC Code]

```cpp #include<bits/stdc++.h> #define int long long #define r(x) for (int i = 1; i <= x; i++) #define rep(i, a, b) for (int i = a; i <= b; i++) #define reb(i, a, b) for (int i = a; i >= b; i--) using namespace std; const int N = 550; int n, q, p[N][N]; char s[N][N]; signed main() { cin.tie(0)->sync_with_stdio(0); cin >> n >> q; r(n) rep(j, 1, n) cin >> s[i][j]; r(n - 1) rep(j, 1, n - 1) { if (s[i][j] == '.' && s[i + 1][j] == '.' && s[i][j + 1] == '.' && s[i + 1][j + 1] == '.') p[i][j]++; p[i][j] += p[i][j - 1]; } r(n - 1) rep(j, 1, n - 1) p[i][j] += p[i - 1][j]; for (int i = 1, u, d, l, r; i <= q; i++) { cin >> u >> d >> l >> r, d--, r--; // 做左上角的点最多到 (d-1, r-1) cout << p[d][r] - p[d][l - 1] - p[u - 1][r] + p[u - 1][l - 1] << "\n"; // 前缀和的容斥 } return 0; } ``` ::::