Official

G - Scalene Triangle Area Editorial by en_translator


For example, if \(K=5\), the top-left piece covers the following 1 squares.

11111111110
11111111000
11111100000
11110000000
11000000000
00000000000

The basic idea is to utilize cumulative sum tricks, which is called “imos method” (article in Japanese) in Japan.
By placing \(+1\) and \(-1\) on the + and - squares below, respectively, we can finally obtain the answer by computing the horizontal cumulative sums from left to right. (We refer by (1) to this operation of taking these cumulative sums, corresponding to res in the sample code)

+.........-
+.......-..
+.....-....
+...-......
+.-........
...........

Let’s consider + and - independently.

Handling +

By placing \(+1\) and \(-1\) on the + and - squares below, respectively, and computing the vertical cumulative sums from top to bottom, we can place \(+1\) to the squares we want to place + in (1) above.
(We refer by (2) to this operation of taking these cumulative sums, corresponding to vert in the sample code)

+..........
...........
...........
...........
...........
-..........
Handling -

This requires a tweak. Consider taking the cumulative sums as follows:
\(Sum[i][j] = Sum[i][j] + Sum[i-1][j+2]\)
This way, we can take the cumulative sum in the “diagonal” direction (technically, in the direction of slope \(1/2\)). By placing \(+1\) and \(-1\) on the + and - squares below, respectively, and computing the “diagonal” cumulative sums, we can place \(-1\) to the squares we want to place - in (1) above.
(We refer by (2) to this operation of taking these cumulative sums, corresponding to diag in the sample code)

..........-
...........
...........
...........
...........
+..........

By placing + and - for each square and taking cumulative sums of (2) and (3), we can obtain the array before taking the cumulative sums (1). Then we can take the cumulative sums (1) to obtain for every square how many pieces covers it. All that left is to answer the queries.

The time and space complexities are \(O(N^2+Q)\) and \(O(N^2)\), respectively.
Note that you need to allocate sufficiently large array because + and - may be placed outside the board in each step.

Sample code (C++):

#include<bits/stdc++.h>

using namespace std;

int main(){
  int n,m;
  cin >> n >> m;
  vector<vector<int>> vert(2022,vector<int>(11111,0));
  vector<vector<int>> diag(2022,vector<int>(11111,0));

  for(int i=0;i<n;i++){
    string s;
    cin >> s;
    for(int j=0;j<n;j++){
      if(s[j]=='O'){
        vert[i][j]++;
        if((i+m)<2022){vert[i+m][j]--;}
        diag[i][j+2*m]--;
        if((i+m)<2022){diag[i+m][j]++;}
      }
    }
  }

  vector<vector<int>> res(2022,vector<int>(11111,0));
  for(int i=1;i<2022;i++){
    for(int j=0;j<11111;j++){
      vert[i][j]+=vert[i-1][j];
      if((j+2)<11111){diag[i][j]+=diag[i-1][j+2];}
    }
  }

  for(int i=0;i<2022;i++){
    for(int j=0;j<11111;j++){
      res[i][j]=diag[i][j]+vert[i][j];
    }
  }

  for(int i=0;i<2022;i++){
    for(int j=1;j<11111;j++){res[i][j]+=res[i][j-1];}
  }
  
  int q;
  cin >> q;
  while(q>0){
    q--;
    int x,y;
    cin >> x >> y;
    x--;y--;
    cout << res[x][y] << '\n';
  }
  return 0;
}

posted:
last update: