Minieye杯第十五届华中科技大学程序设计邀请赛现场同步赛 I Matrix Again
https://ac.nowcoder.com/acm/contest/700/I
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
KK is the engineer responsible for sensor sensing in MINIEYE. KK recently need to use radar to sense the vehicles ahead, and KK thought about it day and night, and finally found a perfect solution.
You are now an intern at KK. To give you an understanding of the principles of radar sensing, KK gives you a simplified version of this problem.
Given a matrix of N×M, each element is an integer. If there is a submatrix of L × L, and the difference between the maximum and the minimum of this submatrix is less than or equal to G, then this submatrix is considered as a car matrix. Now you need to find the largest L.
输入描述:
The first line contains three integers N, M, G(0 < N, M ≤ 500, 0 ≤ G ≤ 200).
Each of the following N lines contains M integers, representing the matrix. It is guaranteed that every integer in the matrix is in the range [-100, 100].
输出描述:
Output the maximum L in a single line.
示例1
输入
3 3 4
0 1 2
3 4 5
6 7 8
输出
2
分析
题目大意就是从一个N*M的矩阵里选取一个L*L的矩阵,使得这个矩阵中的最大值和最小值的差小于等于G,求最大的L。
首先很显然跟RMQ问题,求最大最小值嘛,但是这题是矩阵,那就是二维的RMQ,用ST表实现的,模板++;
在处理完最大最小之后,如果要遍历所有的矩阵时间复杂度过大是不行的,考虑二分,,,然后二分写自闭了,最后还是队友改二分改正确了。
在我打这句话的时候,队内其他大佬用暴力过了这题,,,,,瞬间不想继续写这题的题解了,,,,撤了。
AC代码:
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <time.h>
#include <queue>
#include <list>
#include <string.h>
#define sf scanf
#define pf printf
#define lf double
#define ll long long
#define p123 printf("123\n");
#define pn printf("\n");
#define pk printf(" ");
#define p(n) printf("%d",n);
#define pln(n) printf("%d\n",n);
#define s(n) scanf("%d",&n);
#define ss(n) scanf("%s",n);
#define ps(n) printf("%s",n);
#define sld(n) scanf("%lld",&n);
#define pld(n) printf("%lld",n);
#define slf(n) scanf("%lf",&n);
#define plf(n) printf("%lf",n);
#define sc(n) scanf("%c",&n);
#define pc(n) printf("%c",n);
#define gc getchar();
#define re(n,a) memset(n,a,sizeof(n));
#define len(a) strlen(a)
#define LL long long using namespace std; int val[][];
int mm[];
char dpmin[][][][];//最小值
char dpmax[][][][];//最大值 void initRMQ(int n,int m) {
for(int i = ; i <= n; i++)
for(int j = ; j <= m; j++)
dpmin[i][j][][] = dpmax[i][j][][] = val[i][j];
for(int ii = ; ii <= mm[n]; ii++)
for(int jj = ; jj <= mm[m]; jj++)
if(ii+jj)
for(int i = ; i + (<<ii) - <= n; i++)
for(int j = ; j + (<<jj) - <= m; j++) {
if(ii) {
dpmin[i][j][ii][jj] = min(dpmin[i][j][ii-][jj],dpmin[i+(<<(ii-))][j][ii-][jj]);
dpmax[i][j][ii][jj] = max(dpmax[i][j][ii-][jj],dpmax[i+(<<(ii-))][j][ii-][jj]);
} else {
dpmin[i][j][ii][jj] = min(dpmin[i][j][ii][jj-],dpmin[i][j+(<<(jj-))][ii][jj-]);
dpmax[i][j][ii][jj] = max(dpmax[i][j][ii][jj-],dpmax[i][j+(<<(jj-))][ii][jj-]);
}
}
}
int rmq1(int x1,int y1,int x2,int y2) {
int k1 = mm[x2-x1+];
int k2 = mm[y2-y1+];
x2 = x2 - (<<k1) + ;
y2 = y2 - (<<k2) + ;
return max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2]));
}
//查询矩形的最小值
int rmq2(int x1,int y1,int x2,int y2) {
int k1 = mm[x2-x1+];
int k2 = mm[y2-y1+];
x2 = x2 - (<<k1) + ;
y2 = y2 - (<<k2) + ;
return min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2]));
} int main() {
mm[] = -;
for(int i = ; i <= ; i++)
mm[i] = ((i&(i-))==)?mm[i-]+:mm[i-];
int N,M,g;
scanf("%d%d%d",&N,&M,&g);
for(int i = ; i <= N; i++)
for(int j = ; j <= M; j++)
scanf("%d",&val[i][j]);
initRMQ(N,M);
//
int x,y;
int maxi = -;
for(int i = ; i <= N; i++) {
for(int j = ; j <= M; j++) {
int l = ,r = min(N-i+,M-j+),mid;
int ans;
while(l <= r) {
mid = (l+r) >> ;
if(rmq1(i,j,i+mid-,j+mid-)-rmq2(i,j,i+mid-,j+mid-) > g) {
r = mid-;
//ans = mid;
} else {
l = mid+;
}
}
if(r > maxi) {
maxi = r;
}
}
}
p(maxi) pn return ;
}
其他大佬代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n,m,g;
int a[][];
int b[][];//最大值
int c[][];//最小值
int b1[][];
int c1[][]; int l;
int main()
{
scanf("%d%d%d",&n,&m,&g);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
scanf("%d",&a[i][j]);
if(i>=&&j>=){
b[i-][j-] = max(a[i][j], max(a[i-][j], max(a[i][j-],a[i-][j-]) ) );
c[i-][j-] = min(a[i][j], min(a[i-][j], min(a[i][j-],a[i-][j-]) ) );
}
}
} int x = n-;
int y = m-;
l = min(n,m);
int ans = ;
for(int i = ; i <= l;i++)
{ for(int j = ;j <= x;j++)
{
for(int k = ;k <= y;k++)
{
if(b[j][k] - c[j][k] <= g){
ans = i;
}
}
} for(int j = ;j <= x;j++)
{
for(int k = ;k <= y;k++)
{
b1[j][k] = max(b[j][k] , max(b[j-][k],max(b[j][k-],b[j-][k-])));
b[j-][k-] = b1[j][k];
c1[j][k] = min(c[j][k] , min(c[j-][k],min(c[j][k-],c[j-][k-])));
c[j-][k-] = c1[j][k];
}
}
x--;
y--;
}
cout<<ans<<endl; return ;
}