#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("inline")
#include<bits/stdc++.h>
using namespace std;
template<class T> struct cLtraits_identity{
using type = T;
}
;
template<class T> using cLtraits_try_make_signed =
typename conditional<
is_integral<T>::value,
make_signed<T>,
cLtraits_identity<T>
>::type;
template <class S, class T> struct cLtraits_common_type{
using tS = typename cLtraits_try_make_signed<S>::type;
using tT = typename cLtraits_try_make_signed<T>::type;
using type = typename common_type<tS,tT>::type;
}
;
template<class S, class T> inline auto min_L(S a, T b)
-> typename cLtraits_common_type<S,T>::type{
return (typename cLtraits_common_type<S,T>::type) a <= (typename cLtraits_common_type<S,T>::type) b ? a : b;
}
template<class T> void Unique_L(int &N, T A[], int sorted=0){
int i;
int k;
if(!sorted){
sort(A, A+N);
}
k = 0;
for(i=(0);i<(N);i++){
if(k==0 || A[k-1]!=A[i]){
A[k++] = A[i];
}
}
N = k;
}
template<class T> struct Arr2d{
int n1;
int n2;
int mem1;
int mem2;
T**d;
T* operator[](int a){
return d[a];
}
int set_cumulative_sum45;
int cumulative_sum45_mem;
T**cumulative_sum45;
void setSum45(void){
int i;
int j;
set_cumulative_sum45 = 1;
if(cumulative_sum45_mem < n1+n2+1){
for(i=(0);i<(cumulative_sum45_mem);i++){
delete[] cumulative_sum45[i];
}
delete[] cumulative_sum45;
cumulative_sum45_mem = n1+n2+1;
cumulative_sum45 = new T*[cumulative_sum45_mem];
for(i=(0);i<(cumulative_sum45_mem);i++){
cumulative_sum45[i] = new T[cumulative_sum45_mem];
}
}
for(i=(0);i<(n1+n2+1);i++){
for(j=(0);j<(n1+n2+1);j++){
cumulative_sum45[i][j] = 0;
}
}
for(i=(0);i<(n1);i++){
for(j=(0);j<(n2);j++){
cumulative_sum45[n1-i+j][i+j+1] += d[i][j];
}
}
for(i=(0);i<(n1+n2);i++){
for(j=(0);j<(n1+n2);j++){
cumulative_sum45[i+1][j+1] += cumulative_sum45[i+1][j] + cumulative_sum45[i][j+1] - cumulative_sum45[i][j];
}
}
}
T getSum45(int r1, int c1, int r2, int c2){
int x1;
int x2;
int y1;
int y2;
if(!set_cumulative_sum45){
setSum45();
}
x1 = n1 - 1 - r1 + c1;
y1 = r1 + c1;
x2 = n1 - 1 - r2 + c2;
y2 = r2 + c2;
if(x1 > x2){
swap(x1, x2);
}
if(y1 > y2){
swap(y1, y2);
}
return cumulative_sum45[x2+1][y2+1] - cumulative_sum45[x2+1][y1] - cumulative_sum45[x1][y2+1] + cumulative_sum45[x1][y1];
}
T getSum45Border(int r1, int c1, int r2, int c2){
int x1;
int x2;
int y1;
int y2;
T res;
if(!set_cumulative_sum45){
setSum45();
}
x1 = n1 - 1 - r1 + c1;
y1 = r1 + c1;
x2 = n1 - 1 - r2 + c2;
y2 = r2 + c2;
if(x1 > x2){
swap(x1, x2);
}
if(y1 > y2){
swap(y1, y2);
}
res = cumulative_sum45[x2+1][y2+1] - cumulative_sum45[x2+1][y1] - cumulative_sum45[x1][y2+1] + cumulative_sum45[x1][y1];
if(x2 - x1 > 1 && y2 - y1 > 1){
res -= cumulative_sum45[x2][y2] - cumulative_sum45[x2][y1+1] - cumulative_sum45[x1+1][y2] + cumulative_sum45[x1+1][y1+1];
}
return res;
}
void reset(){
set_cumulative_sum45 = 0;
}
void constructor(){
n1 = n2 = mem1 = mem2 = 0;
d = NULL;
set_cumulative_sum45 = 0;
cumulative_sum45_mem = 0;
cumulative_sum45 = NULL;
}
void destructor(){
int i;
if(d != NULL){
for(i=(0);i<(mem1);i++){
delete[] d[i];
}
delete[] d;
}
d = NULL;
mem1 = mem2 = n1 = n2 = 0;
set_cumulative_sum45 = 0;
if(cumulative_sum45 != NULL){
for(i=(0);i<(cumulative_sum45_mem);i++){
delete[] cumulative_sum45[i];
}
delete[] cumulative_sum45;
}
cumulative_sum45_mem = 0;
cumulative_sum45 = NULL;
}
void constructor(int nn1, int nn2){
constructor();
malloc(nn1, nn2);
}
void memory_expand(int nn1, int nn2){
int i;
if(mem1 < nn1 || mem2 < nn2){
if(d != NULL){
for(i=(0);i<(mem1);i++){
delete[] d[i];
}
delete[] d;
}
d = new T*[nn1];
for(i=(0);i<(nn1);i++){
d[i] = new T[nn2];
}
mem1 = nn1;
mem2 = nn2;
}
}
void malloc(int nn1, int nn2){
reset();
memory_expand(nn1, nn2);
n1 = nn1;
n2 = nn2;
}
void setN(int nn1, int nn2){
reset();
memory_expand(nn1, nn2);
n1 = nn1;
n2 = nn2;
}
void set(vector<vector<T>> &a){
int i;
int j;
int nn1 = a.size();
int nn2 = a[0].size();
setN(nn1, nn2);
for(i=(0);i<(nn1);i++){
for(j=(0);j<(nn2);j++){
d[i][j] = a[i][j];
}
}
}
void set(int nn1, int nn2, T **a){
int i;
int j;
setN(nn1, nn2);
for(i=(0);i<(nn1);i++){
for(j=(0);j<(nn2);j++){
d[i][j] = a[i][j];
}
}
}
void free(){
destructor();
}
Arr2d(){
constructor();
}
Arr2d(int nn1, int nn2){
constructor(nn1, nn2);
}
~Arr2d(){
destructor();
}
}
;
#define main dummy_main
int main(){
return 0;
}
#undef main
int X;
int Y;
int sz;
int arr[1000000];
Arr2d<int> A;
class Solution{
public:
vector<int> getBiggestThree(vector<vector<int>>& grid){
int i;
dummy_main();
sz = 0;
X = grid.size();
Y = grid[0].size();
A.set(grid);
for(i=(0);i<(X);i++){
int j;
for(j=(0);j<(Y);j++){
int k;
for(k=(0);k<(101);k++){
if(i+2*k >= X || j-k < 0 || j+k >= Y){
break;
}
arr[sz++] = A.getSum45Border(i,j,i+2*k,j);
}
}
}
Unique_L(sz,arr);
vector<int> res;
for(i=(0);i<(min_L(3, sz));i++){
res.push_back(arr[sz-1-i]);
}
return res;
}
}
;
// cLay version 20210607-1
// --- original code ---
// #define main dummy_main
// {}
// #undef main
//
// int X, Y, sz, arr[1d6];
// Arr2d<int> A;
//
// class Solution {
// public:
// vector<int> getBiggestThree(vector<vector<int>>& grid) {
// dummy_main();
// sz = 0;
// X = grid.size();
// Y = grid[0].size();
// A.set(grid);
// rep(i,X) rep(j,Y) rep(k,101){
// if(i+2*k >= X || j-k < 0 || j+k >= Y) break;
// arr[sz++] = A.getSum45Border(i,j,i+2*k,j);
// }
// Unique(sz,arr);
//
// VI res;
// rep(i,min(3,sz)) res.push_back(arr[sz-1-i]);
// return res;
// }
// };