https://codeforces.com/gym/102769/problem/B
写完到调试到对拍出来前前后后用了6个小时,写这种码农题还是功力不够。。。现场感觉是不可能写出来的,现场也只有pku和渡渡鸟过了这题
思路挺简单的,就枚举这个点在分别的左右上下边界上
大致讲一下在左边界上怎么求最大的矩形
首先l[i][j]表示i能连续最左边到哪,也就是最小的j,r[i][j]为最优边,u[i][j]为最上边也就是最小的x,d[i][j]最下边
然后先求出上边最高可以到哪,由于(x,y)在左边界,我们就去枚举右边界的j,然后首先a[x][j]必须是有的,然后对于他能拓展到的最高的ua[x][j],x最小可以是多少,这个东西可以在树状数组上二分完成,树状数组存长度为下标,前缀和为有多少条a(i,y)可以拓展到j的,也就是需要预处理(x,y)向上走也就是(i<x),y)可以向右拓展的最远距离,先把他们全部加入树状数组中,再把他们加入向右最远距离的消除vector中
然后枚举右边界j增加的时候,先树状数组上二分找到能够到当前j中,且左边界和右边界向上都能够着的区间中,最大长度是多少,然后再看有哪些这里过后就够不到j+1的(i<x,y)向右拓展的长度,吧他们从树状数组中删掉。
这样我们就求出了(x,y)为左边界,且对于每个j能向上最多到多远,然后再求一遍向下最多能到多远,这就求出了左边界的最大矩阵。然后类似地求上下左右就行了
我吐了,应该有简单一点的写法但我不会写,比如四个方向都抽象一下放到一个函数里面,但感觉不会啊
#include<bits/stdc++.h>
using namespace std;
const int maxl=1010;
int n,m,q,len;
int b[2][maxl],c[2][maxl],bit[2][maxl];
int a[maxl][maxl];
int la[maxl][maxl],ra[maxl][maxl],ua[maxl][maxl],da[maxl][maxl];
char s[maxl];
vector <int> out[2][maxl];
inline void prework()
{
scanf("%d%d%d",&n,&m,&q);
len=max(n,m);
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
for(int j=1;j<=m;j++)
a[i][j]=(s[j]=='#')?1:0;
}
for(int i=1;i<=n+1;i++) a[i][m+1]=0;
for(int i=1;i<=m+1;i++) a[n+1][i]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
if(a[i][j]==0)
la[i][j]=0;
else if(j-1>0 && a[i][j-1])
la[i][j]=la[i][j-1];
else
la[i][j]=j;
for(int j=m;j>=1;j--)
if(a[i][j]==0)
ra[i][j]=0;
else if(j+1<=m && a[i][j+1])
ra[i][j]=ra[i][j+1];
else
ra[i][j]=j;
}
for(int j=1;j<=m;j++)
{
for(int i=1;i<=n;i++)
if(a[i][j]==0)
ua[i][j]=0;
else if(i-1>0 && a[i-1][j])
ua[i][j]=ua[i-1][j];
else
ua[i][j]=i;
for(int i=n;i>=1;i--)
if(a[i][j]==0)
da[i][j]=0;
else if(i+1<=n && a[i+1][j])
da[i][j]=da[i+1][j];
else
da[i][j]=i;
}
}
inline void chg(int x,int y)
{
if(a[x][y]==1)
{
ra[x][y]=(y+1<=m && a[x][y+1])?ra[x][y+1]:y;
for(int j=y-1;j>=1 && a[x][j];j--)
if(a[x][j])
ra[x][j]=ra[x][j+1];
la[x][y]=(y-1>=1 && a[x][y-1])?la[x][y-1]:y;
for(int j=y+1;j<=m && a[x][j];j++)
la[x][j]=la[x][j-1];
ua[x][y]=(x-1>=1 && a[x-1][y])?ua[x-1][y]:x;
for(int i=x+1;i<=n && a[i][y];i++)
ua[i][y]=ua[i-1][y];
da[x][y]=(x+1<=n && a[x+1][y])?da[x+1][y]:x;
for(int i=x-1;i>=1 && a[i][y];i--)
da[i][y]=da[i+1][y];
}
else
{
ua[x][y]=da[x][y]=la[x][y]=ra[x][y]=0;
if(y-1>0 && a[x][y-1])
for(int j=y-1;j>=1 && a[x][j];j--)
ra[x][j]=y-1;
if(y+1<=m && a[x][y+1])
for(int j=y+1;j<=m && a[x][j];j++)
la[x][j]=y+1;
if(x+1<=n && a[x+1][y]);
for(int i=x+1;i<=n && a[i][y];i++)
ua[i][y]=x+1;
if(x-1>0 && a[x-1][y])
for(int i=x-1;i>=1 && a[i][y];i--)
da[i][y]=x-1;
}
}
inline void add(int i,int x,int bit[])
{
while(i<=len)
{
bit[i]+=x;
i+=i&-i;
}
}
inline int sum(int i,int bit[])
{
int ret=0;
while(i)
{
ret+=bit[i];
i-=i&-i;
}
return ret;
}
inline int qry(int d,int bit[])
{
int ret=0,sum=0;
for(int i=10;i>=0;i--)
if(ret+(1<<i)<=len && sum+bit[ret+(1<<i)]<d)
ret+=1<<i,sum+=bit[ret];
return ret+1;
}
inline void init(int a[2][maxl])
{
for(int i=1;i<=len;i++)
{
bit[0][i]=bit[1][i]=0;
out[0][i].clear();out[1][i].clear();
a[0][i]=a[1][i]=0;
}
}
inline void mainwork()
{
int op,x,y,l1,l2,ans,d;
for(int cas=1;cas<=q;cas++)
{
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
a[x][y]^=1;
chg(x,y);
}
else
{
if(!a[x][y])
{
puts("0");
continue;
}
ans=1;
init(b);
l1=b[0][0]=b[1][0]=x-ua[x][y]+1;//up down left 0/right 1
for(int i=x;i>=1 && a[i][y];i--)
{
if(y-la[i][y]>0)
add(x-i+1,1,bit[0]),out[0][y-la[i][y]].push_back(x-i+1);
if(ra[i][y]-y>0)
add(x-i+1,1,bit[1]),out[1][ra[i][y]-y].push_back(x-i+1);
}
for(int j=y-1;j>=1;j--)
{
if(a[x][j])
{
l2=x-ua[x][j]+1;
d=sum(min(l1,l2),bit[0]);
b[0][y-j]=(d==0)?0:qry(d,bit[0]);
}
for(int id:out[0][y-j])
add(id,-1,bit[0]);
}
for(int j=y+1;j<=m;j++)
{
if(a[x][j])
{
l2=x-ua[x][j]+1;
d=sum(min(l1,l2),bit[1]);
b[1][j-y]=(d==0)?0:qry(d,bit[1]);
}
for(int id:out[1][j-y])
add(id,-1,bit[1]);
}
init(c);
l1=c[0][0]=c[1][0]=da[x][y]-x+1;
for(int i=x;i<=n && a[i][y];i++)
{
if(y-la[i][y]>0)
add(i-x+1,1,bit[0]),out[0][y-la[i][y]].push_back(i-x+1);
if(ra[i][y]-y>0)
add(i-x+1,1,bit[1]),out[1][ra[i][y]-y].push_back(i-x+1);
}
for(int j=y-1;j>=1;j--)
{
if(a[x][j])
{
l2=da[x][j]-x+1;
d=sum(min(l1,l2),bit[0]);
c[0][y-j]=(d==0)?0:qry(d,bit[0]);
}
for(int id:out[0][y-j])
add(id,-1,bit[0]);
}
for(int j=y+1;j<=m;j++)
{
if(a[x][j])
{
l2=da[x][j]-x+1;
d=sum(min(l1,l2),bit[1]);
c[1][j-y]=(d==0)?0:qry(d,bit[1]);
}
for(int id:out[1][j-y])
add(id,-1,bit[1]);
}
for(int i=0;i<=len;i++)
{
if(b[0][i] && c[0][i])
ans=max(ans,(b[0][i]+c[0][i]-1)*(i+1));
if(b[1][i] && c[1][i])
ans=max(ans,(b[1][i]+c[1][i]-1)*(i+1));
}
init(b);
l1=b[0][0]=b[1][0]=y-la[x][y]+1; // left right up 0/down 1
for(int j=y;j>=1 && a[x][j];j--)
{
if(x-ua[x][j]>0)
add(y-j+1,1,bit[0]),out[0][x-ua[x][j]].push_back(y-j+1);
if(da[x][j]-x>0)
add(y-j+1,1,bit[1]),out[1][da[x][j]-x].push_back(y-j+1);
}
for(int i=x-1;i>=1;i--)
{
if(a[i][y])
{
l2=y-la[i][y]+1;
d=sum(min(l1,l2),bit[0]);
b[0][x-i]=(d==0)?0:qry(d,bit[0]);
}
for(int id:out[0][x-i])
add(id,-1,bit[0]);
}
for(int i=x+1;i<=n;i++)
{
if(a[i][y])
{
l2=y-la[i][y]+1;
d=sum(min(l1,l2),bit[1]);
b[1][i-x]=(d==0)?0:qry(d,bit[1]);
}
for(int id:out[1][i-x])
add(id,-1,bit[1]);
}
init(c);
l1=c[0][0]=c[1][0]=ra[x][y]-y+1;
for(int j=y;j<=m && a[x][j];j++)
{
if(x-ua[x][j]>0)
add(j-y+1,1,bit[0]),out[0][x-ua[x][j]].push_back(j-y+1);
if(da[x][j]-x>0)
add(j-y+1,1,bit[1]),out[1][da[x][j]-x].push_back(j-y+1);
}
for(int i=x-1;i>=1;i--)
{
if(a[i][y])
{
l2=ra[i][y]-y+1;
d=sum(min(l1,l2),bit[0]);
c[0][x-i]=(d==0)?0:qry(d,bit[0]);
}
for(int id:out[0][x-i])
add(id,-1,bit[0]);
}
for(int i=x+1;i<=n;i++)
{
if(a[i][y])
{
l2=ra[i][y]-y+1;
d=sum(min(l1,l2),bit[1]);
c[1][i-x]=(d==0)?0:qry(d,bit[1]);
}
for(int id:out[1][i-x])
add(id,-1,bit[1]);
}
for(int i=0;i<=len;i++)
{
if(b[0][i] && c[0][i])
ans=max(ans,(b[0][i]+c[0][i]-1)*(i+1));
if(b[1][i] && c[1][i])
ans=max(ans,(b[1][i]+c[1][i]-1)*(i+1));
}
printf("%d\n",ans);
}
}
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
printf("Case #%d:\n",i);
mainwork();
}
return 0;
}