Official

D - 画像回転エディタ / Image Rotation Editor Editorial by kyopro_friends


以下、index は 0 からとします。

まず「\(K\times K\) のグリッド全体を右に \(90\) 度回す」という操作を考えます。 このとき、\((i,j)\) のマスは \((j,K-1-i)\) に移ります。よって

for i in 0..K-1:
  for j in 0..K-1:
    T[j][K-1-i]=S[i][j]

のような方法により、\(S\) を右に \(90\) 度回したグリッド \(T\) を得ることができます。

元の問題もほとんど同様に、\((r,c)\) を左上とする \(K\times K\) の範囲を右に \(90\) 度回したグリッドは

for i in 0..K-1:
  for j in 0..K-1:
    T[j][K-1-i]=S[r+i][c+j]

のように得ることができます。こうして得られたグリッドで元のグリッドを上書きすることで、所望の操作を実現できます。

クエリ \(1\) 回あたりの計算量は \(O(K^2)\) なので全体の計算量は \(O(QK^2)\) となります。\(QK^2 \leq 2\times 10^7\) の制約より、この解法は十分高速です。

実装例 (C++)

#include<bits/stdc++.h>
using namespace std;

int main(){
  int n, k, q;
  cin >> n >> k >> q;
  vector<string> s(n);
  for(int i=0; i<n; i++) cin >> s[i];
  vector<string> t(k, string(k, '0'));

  for(int i=0; i<q; i++){
    int r, c;
    cin >> r >> c;
    r--, c--;
    for(int i=0; i<k; i++){
      for(int j=0; j<k; j++){
        t[j][k-1-i] = s[r+i][c+j];
      }
    }
    for(int i=0; i<k; i++){
      for(int j=0; j<k; j++){
        s[r+i][c+j] = t[i][j];
      }
    }
  }

  for(int i=0; i<n; i++) cout << s[i] << endl;
}

実装例 (Python)

N, K, Q = map(int, input().split())
S = [list(input()) for _ in range(N)]
T = [['0']*K for _ in range(K)]

for _ in range(Q):
  r, c = map(int, input().split())
  r -= 1
  c -= 1
  for i in range(K):
    for j in range(K):
      T[j][K-1-i] = S[r+i][c+j]
  for i in range(K):
    for j in range(K):
      S[r+i][c+j] = T[i][j]

for s in S:
  print("".join(s))

posted:
last update: