나무 심기
문제 해결 아이디어
각 하부 경계 열거 한 모든 대응하는 상부 경계를 열거, 최소값, 최대 값 및 최소값이 서서히 갱신 상부 경계로 감소 될 수있는 현재의 경계로서 최대 간격에 대응하는 획득된다. 이 최대 값과 최소값이어서 초기 좌측 경계 설정 단조로운 큐에 배치되고, 우측 경계는 현재로드 지수, 즉이 때 높은 열거 높은이다. 그 최대 값의 위치 및 팀 앞의 최소값, 그리고 어떤 큐 해제 첨자 +1의 좌단이되도록 현재의 최대 및 최소 간격의 차이는, m을 초과 할 경우. 각 영역에 대해 산출 된 조건을 만족하는 최대 값 캔 걸린다.
다음 코드는
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
inline int read(){
int res = 0, w = 0; char ch = 0;
while(!isdigit(ch)){
w |= ch == '-', ch = getchar();
}
while(isdigit(ch)){
res = (res << 3) + (res << 1) + (ch ^ 48);
ch = getchar();
}
return w ? -res : res;
}
const int N = 505;
int a[N][N];
int minn[N], maxx[N];
struct T{
int i, val;
T(int val, int i): val(val), i(i){}
};
int main()
{
int t;
scanf("%d", &t);
while(t --){
int n, m;
n = read(), m = read();
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++)
a[i][j] = read();
}
int ans = 0;
for(int i = 1; i <= n; i ++){
for(int j = i; j >= 1; j --){
if(j == i){
for(int k = 1; k <= n; k ++)
minn[k] = maxx[k] = a[j][k];
}
else {
for(int k = 1; k <= n; k ++){
minn[k] = min(minn[k], a[j][k]);
maxx[k] = max(maxx[k], a[j][k]);
}
}
int dq1[N], dq2[N];
int l1, r1, l2, r2;
l1 = l2 = r1 = r2 = 0;
int l = 1;
for(int k = 1; k <= n; k ++){
while(l1 != r1 && minn[dq1[r1 - 1]] > minn[k])
-- r1;
while(l2 != r2 && maxx[dq2[r2 - 1]] < maxx[k])
-- r2;
dq1[r1 ++] = k;
dq2[r2 ++] = k;
while(l1 != r1 && l2 != r2 && maxx[dq2[l2]] - minn[dq1[l1]] > m){
int x1 = dq1[l1];
int x2 = dq2[l2];
l = min(x1, x2) + 1;
if(x1 <= x2)
l1 ++;
if(x1 >= x2)
l2 ++;
}
ans = max(ans, (i - j + 1) * (k - l + 1));
}
}
}
printf("%d\n", ans);
}
return 0;
}