title
HDU 2870
Problem Description
Now here is a matrix with letter ‘a’,‘b’,‘c’,‘w’,‘x’,‘y’,‘z’ and you can change ‘w’ to ‘a’ or ‘b’, change ‘x’ to ‘b’ or ‘c’, change ‘y’ to ‘a’ or ‘c’, and change ‘z’ to ‘a’, ‘b’ or ‘c’. After you changed it, what’s the largest submatrix with the same letters you can make?
Input
The input contains multiple test cases. Each test case begins with m and n (1 ≤ m, n ≤ 1000) on line. Then come the elements of a matrix in row-major order on m lines each with n letters. The input ends once EOF is met.
Output
For each test case, output one line containing the number of elements of the largest submatrix of all same letters.
Sample Input
2 4
abcw
wxyz
Sample Output
3
Source
Recommend
gaojie | We have carefully selected several similar problems for you: 2830 2577 1505 2845 1069
analysis
书上标明的是单调队列优化 ,然而我好像没用到单调队列?不懂哎。。
看题看了一小时,没有任何思路,只好去翻了题解,原来这么简单。我真服自己了。看来还是对模型不够熟悉啊,得加把劲儿了。。
正式题解:w x y z 可以各自 变成a ,b ,c 中的几种, 那么只需要考虑矩阵由 a, b 或 c 构成就可以了。
对于每一种情况都枚举一次(一共也就三种), 比如现在考虑由 a 构成的矩阵, 只需要将能 w y z a 的位置记为 1, 其他位置记为 0 ,然后找面积最大的 由 1 组成的矩阵即可。
那么这题就要用到单调栈,不会的同学可以去这边学。其实我也不会
code
没用单调栈,耗时280MS
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getc();
while (!isdigit(ch) && ch^'-') ch=getc();
if (ch=='-') f=-1, ch=getc();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getc();
x*=f;
}
template<typename T>inline void write(T &x)
{
if (!x) { putchar('0'),putchar('\n'); return ; }
if (x<0) putchar('-'),x=-x;
T num=0,ch[16];
while (x) ch[++num]=x%10+48,x/=10;
while (num) putchar(ch[num--]);
putchar('\n');
}
char s[maxn][maxn],key[maxn][maxn];
int l[maxn],r[maxn],cnt[maxn][maxn],n,m,ans;
inline void solve(char x,char a,char b,char c)
{
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j)
if (s[i][j]==a || s[i][j]==b || s[i][j]==c) key[i][j]=x;
else key[i][j]=s[i][j];
for (int i=1; i<=n; ++i)
{
cnt[i][0]=cnt[i][m+1]=-1;
for (int j=1; j<=m; ++j)
{
l[j]=r[j]=j;
if (key[i][j]^x) cnt[i][j]=0;
else cnt[i][j]=cnt[i-1][j]+1;
}
for (int j=2; j<=m; ++j)
if (cnt[i][j])
while (cnt[i][l[j]-1]>=cnt[i][j]) l[j]=l[l[j]-1];
for (int j=m-1; j; --j)
if (cnt[i][j])
while (cnt[i][r[j]+1]>=cnt[i][j]) r[j]=r[r[j]+1];
for (int j=1; j<=m; ++j)
if (cnt[i][j]) ans=max(ans,(r[j]-l[j]+1)*cnt[i][j]);
}
}
int main()
{
while (~scanf("%d %d",&n,&m))
{
for (int i=1; i<=n; ++i) scanf("%s",s[i]+1);
ans=0;
solve('a','w','y','z');
solve('b','w','x','z');
solve('c','x','y','z');
write(ans);
}
return 0;
}
用了单调栈,耗时312MS,怎么还慢了
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getc();
while (!isdigit(ch) && ch^'-') ch=getc();
if (ch=='-') f=-1, ch=getc();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getc();
x*=f;
}
template<typename T>inline void write(T &x)
{
if (!x) { putchar('0'),putchar('\n'); return ; }
if (x<0) putchar('-'),x=-x;
T num=0,ch[16];
while (x) ch[++num]=x%10+48,x/=10;
while (num) putchar(ch[num--]);
putchar('\n');
}
char a[maxn][maxn];
int cnt[maxn][maxn];
inline int fun(char a,char b)
{
if (b=='a' && (a=='a' || a=='w' || a=='y' || a=='z') ) return 1;
if (b=='b' && (a=='b' || a=='w' || a=='x' || a=='z') ) return 1;
if (b=='c' && (a=='c' || a=='x' || a=='y' || a=='z') ) return 1;
return 0;
}
int s[maxn],top;
int l[maxn],r[maxn];
int num[maxn],n,m,ans;
inline void solve()
{
memset(num,0,sizeof(num));
for (int i=1; i<=n; ++i)
{
for (int j=1; j<=m; ++j)
if (cnt[i][j]) ++num[j];
else num[j]=0;
top=0;
for (int j=1; j<=m; ++j)
{
int lef=0;
while (top)
{
lef=s[top];
if (num[lef]>=num[j]) --top;
else break;
}
s[++top]=j,l[j]=lef;
}
top=0;
for (int j=m; j>=1; --j)
{
int rig=m+1;
while (top)
{
rig=s[top];
if (num[rig]>=num[j]) --top;
else break;
}
s[++top]=j,r[j]=rig;
}
for (int j=1; j<=m; ++j) ans=max(ans,num[j]*(r[j]-l[j]-1));
}
}
int main()
{
while (~scanf("%d %d",&n,&m))
{
for (int i=1; i<=n; ++i) scanf("%s",a[i]+1);
ans=0;
for (char k='a'; k<='c'; ++k)
{
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j)
if (fun(a[i][j],k)) cnt[i][j]=1;
else cnt[i][j]=0;
solve();
}
write(ans);
}
return 0;
}