Sizes of Four Diagonal Regions
National Olympiad — National round (2021 season)
Submission name: diag.cpp
Problem summary
Two 45-degree diagonals through cell (R,S) of an M-by-N grid are coloured. Count the white cells in each of the four resulting wedges, using zero for absent wedges, and sort the four counts.
Input
M N S R, with rows numbered bottom to top.
Output
The four region sizes in increasing order.
Constraints
5 ≤ M,N ≤ 10^9; 1 ≤ R ≤ M; 1 ≤ S ≤ N.
Worked example
Input and output for the worked example discussed below.
Input
9 10 3 5
Output
4 15 15 43
Solution analysis
- The white cells split into left, right, above, and below the coloured diagonal X. At distance d≥1 from the centre in one chosen direction, a wedge can contain perpendicular offsets −(d−1)…d−1.
- Let D be the available distance in that direction and A,B the distances to the two perpendicular boundaries. At layer d the count is 1+min(A,d−1)+min(B,d−1). Sum for d=1…D using triangular-number formulas rather than visiting up to a billion layers.
- Define cappedSum(A,L)=Σ from t=0 to L of min(A,t). It is L(L+1)/2 when L≤A, otherwise A(A+1)/2+(L−A)A. A wedge size is D+cappedSum(A,D−1)+cappedSum(B,D−1).
- For M=9,N=10,S=3,R=5, the left wedge has D=2 and size 4. Both vertical wedges have size 15, while the right wedge has size 43. Sorting produces 4 15 15 43.
Why it works
Each white cell has exactly one of |horizontal offset|>|vertical offset| or its reverse, with a unique sign deciding its wedge. For a fixed directional distance d, the strict inequality gives exactly the stated clipped perpendicular range. Summing these disjoint layers counts each region exactly, and closed forms evaluate those sums.
Watch out. Input is M N S R, not M N R S. Coloured diagonal cells are excluded by d−1. Handle D=0 separately, and promote products to long long.
Commented C++17 solution
An independently written complete program with standard headers.
#include<algorithm>
#include<array>
#include<iostream>
using namespace std;
long long cappedSum(long long cap,long long last){
if(last<=cap){
return last*(last+1)/2;
}
return cap*(cap+1)/2+(last-cap)*cap;
}
long long wedge(long long depth,long long firstSide,long long secondSide){
if(depth==0){
return 0;
}
// At distance d, only perpendicular offsets of magnitude below d survive.
return depth+cappedSum(firstSide,depth-1)+cappedSum(secondSide,depth-1);
}
int main(){
long long rows,columns,column,row;
cin>>rows>>columns>>column>>row;
array<long long,4>answer={wedge(column-1,row-1,rows-row),
wedge(columns-column,row-1,rows-row),wedge(row-1,column-1,columns-column),
wedge(rows-row,column-1,columns-column)};
sort(answer.begin(),answer.end());
cout<<answer[0]<<' '<<answer[1]<<' '<<answer[2]<<' '<<answer[3]<<'\n';
}