答案显然是
O
(
log
n
)
\mathcal O(\log n)
O(logn)级别的,并且有很强的单调性。
考虑一轮轮的做,设
F
[
i
]
[
j
]
[
k
]
F[i][j][k]
F[i][j][k]表示左上角为
(
i
,
j
)
(i,j)
(i,j),右上角为
(
i
,
k
)
(i,k)
(i,k)的矩形,用不超过
T
T
T轮最多覆盖多少行。
由
T
T
T推到
T
+
1
T+1
T+1的时候有两种转移,一种容易处理,另一种网上很多题解说要二分,其实可以再设
G
[
i
]
[
j
]
[
k
]
G[i][j][k]
G[i][j][k]表示左上角为
(
j
,
i
)
(j,i)
(j,i),左下角为
(
k
,
i
)
(k,i)
(k,i)的矩形,用不超过
T
T
T轮最多覆盖多少列,这样DP的时候可以交错更新。
时间复杂度
O
(
n
3
log
n
)
\mathcal O(n^3\log n)
O(n3logn)。
#include <bits/stdc++.h>
using namespace std;
inline void update(int &x,int y) {
x=max(x,y);
}
char str[205][205];
int row[205][205],col[205][205];
int f[205][205][205],g[205][205][205];
void pre(int n,int m) {
for(int i=1;i<=n;i++)
for(int j=m;j>0;j--) row[i][j]=((str[i][j]==str[i][j+1])?row[i][j+1]:0)+1;
for(int i=1;i<=m;i++)
for(int j=n;j>0;j--) col[j][i]=((str[j+1][i]==str[j][i])?col[j+1][i]:0)+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) {
f[i][j][j]=col[i][j];
for(int k=j+1;k<=m;k++)
f[i][j][k]=min(f[i][j][k-1],(str[i][k]==str[i][k-1])?col[i][k]:0);
}
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++) {
g[i][j][j]=row[j][i];
for(int k=j+1;k<=n;k++)
g[i][j][k]=min(g[i][j][k-1],(str[k][i]==str[k-1][i])?row[k][i]:0);
}
}
int cur1[205][205][205],cur2[205][205][205];
void dp(int n,int m) {
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=j;k<=m;k++) {
f[i][j][k]+=f[i+f[i][j][k]][j][k];
if (f[i][j][k]) update(cur1[j][i][i+f[i][j][k]-1],k-j+1);
}
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
for(int k=j;k<=n;k++) {
g[i][j][k]+=g[i+g[i][j][k]][j][k];
if (g[i][j][k]) update(cur2[j][i][i+g[i][j][k]-1],k-j+1);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=m;k>=j;k--) update(f[i][j][k],max(f[i][j][k+1],cur2[i][j][k]));
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
for(int k=n;k>=j;k--) update(g[i][j][k],max(g[i][j][k+1],cur1[i][j][k]));
}
int main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%s",str[i]+1);
pre(n,m);
int ans=0;
while (f[1][1][m]<n) {
ans++;
dp(n,m);
}
printf("%d\n",ans);
return 0;
}