Official
C - 都市計画と道路整備 / Urban Planning and Road Development Editorial
by
C - 都市計画と道路整備 / Urban Planning and Road Development Editorial
by
kyopro_friends
以下の図で # で表される長方形領域が道路に変わるとき、新たに道路に隣接するようになる建物が存在しうるのは、 @ で表される位置に限ります。
........ ..@@@@.. .@####@. .@####@. .@####@. ..@@@@.. ........
\(\sum_{k=1}^{Q} \left( 2(D_k-U_k+1) + 2(R_k-L_k+1) \right) \leq 5 \times 10^6\) の制約より、各クエリに対してこのような位置を全て調べることで、実行時間制限に間に合わせることができます。
同じ建物を2度以上数えることがないようにするためには、道路に接続した建物は破壊するのが最も単純です。
実装例 (C++)
#include<bits/stdc++.h>
using namespace std;
int main(){
int h, w, q;
cin >> h >> w >> q;
vector<string> s(h);
for(int i=0; i<h; i++) cin >> s[i];
int ans = 0;
vector<pair<int,int>> d4({{0, 1}, {0, -1}, {1, 0}, {-1, 0}});
for(int i=0; i<h; i++){
for(int j=0; j<w; j++){
if(s[i][j] == 'B'){
bool ok = false;
for(auto[di, dj]: d4){
int ii = i + di;
int jj = j + dj;
if(0 <= ii && ii < h && 0 <= jj && jj < w && s[ii][jj] == 'R'){
ok = true;
}
}
if(ok){
s[i][j] = '.';
ans++;
}
}
}
}
auto check=[&](int i, int j){
if(s[i][j] == 'B'){
s[i][j] = '.';
ans++;
}
};
for(int i=0; i<q; i++){
int u, d, l, r;
cin >> u >> d >> l >> r;
u--, l--;
if(l-1 >= 0){
for(int i=u; i<d; i++){
check(i, l-1);
}
}
if(r < w){
for(int i=u; i<d; i++){
check(i, r);
}
}
if(u-1 >= 0){
for(int j=l; j<r; j++){
check(u-1, j);
}
}
if(d < h){
for(int j=l; j<r; j++){
check(d, j);
}
}
cout << ans << endl;
}
}
実装例 (Python)
H, W, Q = map(int, input().split())
S = [list(input()) for _ in range(H)]
ans = 0
for i in range(H):
for j in range(W):
if S[i][j] == 'B':
ok = False
for di, dj in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
ii = i + di
jj = j + dj
if 0 <= ii < H and 0 <= jj < W and S[ii][jj] == 'R':
ok = True
if ok:
S[i][j]='.'
ans += 1
def check(i, j):
global ans
if S[i][j] == 'B':
S[i][j] = '.'
ans += 1
for _ in range(Q):
U, D, L, R = map(int, input().split())
U -= 1
L -= 1
if L-1 >= 0:
for i in range(U, D):
check(i, L-1)
if R < W:
for i in range(U, D):
check(i, R)
if U-1 >= 0:
for j in range(L, R):
check(U-1, j)
if D < H:
for j in range(L, R):
check(D, j)
print(ans)
