维护每个点最左边/右边/上边的’.'位置
每次查询建立线段树然后枚举高度查找两边长度即可
#include<bits/stdc++.h>
using namespace std;
#define memarray(a,b) memset(a,b,sizeof(a))
#define pb push_back
const long long mod=1e9+7;
const int MAXN=1e3+10;
const int N=3e2+10;
const int INF=0x3f;
int n,m;
int q;
char str[MAXN][MAXN];
int mostH[MAXN][MAXN];
int mostD[MAXN][MAXN];
int mostL[MAXN][MAXN];
int mostR[MAXN][MAXN];
void changeUP(int x,int y){
if(str[x][y]=='.'){
mostH[x][y]=-1;
}else{
if(x==1){
mostH[x][y]=1;
}else{
if(str[x-1][y]=='#')mostH[x][y]=mostH[x-1][y];
else mostH[x][y]=x;
}
}
for(int i=x+1;i<=n;i++){
if(str[i][y]=='.')break;
if(str[i-1][y]=='#') mostH[i][y]=mostH[i-1][y];
else mostH[i][y]=i;
}
}
void changeDOWN(int x,int y){
if(str[x][y]=='.'){
mostD[x][y]=-1;
}else{
if(x==n){
mostD[x][y]=n;
}else{
if(str[x+1][y]=='#')mostD[x][y]=mostD[x+1][y];
else mostD[x][y]=x;
}
}
for(int i=x-1;i>=1;i--){
if(str[i][y]=='.')break;
if(str[i+1][y]=='#') mostD[i][y]=mostD[i+1][y];
else mostD[i][y]=i;
}
}
void changeLEFT(int x,int y){
if(str[x][y]=='.'){
mostL[x][y]=-1;
}else{
if(y==1){
mostL[x][y]=1;
}else{
if(str[x][y-1]=='#')mostL[x][y]=mostL[x][y-1];
else mostL[x][y]=y;
}
}
for(int i=y+1;i<=m;i++){
if(str[x][i]=='.')break;
if(str[x][i-1]=='#') mostL[x][i]=mostL[x][i-1];
else mostL[x][i]=i;
}
}
void changeRIGHT(int x,int y){
if(str[x][y]=='.'){
mostR[x][y]=-1;
}else{
if(y==m){
mostR[x][y]=m;
}else{
if(str[x][y+1]=='#')mostR[x][y]=mostR[x][y+1];
else mostR[x][y]=y;
}
}
for(int i=y-1;i>=1;i--){
if(str[x][i]=='.')break;
if(str[x][i+1]=='#') mostR[x][i]=mostR[x][i+1];
else mostR[x][i]=i;
}
}
int tmpL[MAXN];
int treeMAX[MAXN<<2],treeMIN[MAXN<<2],tmptree[MAXN];
int treeR[MAXN<<2],treeL[MAXN<<2];
void build(int l,int r,int rt){
if(l==r){
treeMAX[rt]=tmptree[l];
treeMIN[rt]=tmptree[l];
treeR[rt]=treeL[rt]=l;
return;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
treeMAX[rt]=max(treeMAX[rt<<1],treeMAX[rt<<1|1]);
treeMIN[rt]=min(treeMIN[rt<<1],treeMIN[rt<<1|1]);
}
int queryMIN(int l,int r,int rt,int L,int R,int h,int flag){
int mid=(l+r)>>1;
if(l==r){
if(flag){
if(treeMAX[rt]>=h)return l;
}else{
if(treeMIN[rt]<=h)return l;
}
return 1e5;
}
if(L<=l&&R>=r){
if(flag){
if(treeMAX[rt<<1]>=h)return queryMIN(l,mid,rt<<1,L,R,h,flag);
else if(treeMAX[rt<<1|1]>=h) return queryMIN(mid+1,r,rt<<1|1,L,R,h,flag);
}else{
if(treeMIN[rt<<1]<=h)return queryMIN(l,mid,rt<<1,L,R,h,flag);
else if(treeMIN[rt<<1|1]<=h) return queryMIN(mid+1,r,rt<<1|1,L,R,h,flag);
}
return 1e5;
}
int ret=1e5;
if(flag){
if(mid>=L&&treeMAX[rt<<1]>=h)ret=min(ret,queryMIN(l,mid,rt<<1,L,R,h,flag));
if(R>=mid+1&&treeMAX[rt<<1|1]>=h)ret=min(ret,queryMIN(mid+1,r,rt<<1|1,L,R,h,flag));
}else{
if(mid>=L&&treeMIN[rt<<1]<=h)ret=min(ret,queryMIN(l,mid,rt<<1,L,R,h,flag));
if(R>=mid+1&&treeMIN[rt<<1|1]<=h)ret=min(ret,queryMIN(mid+1,r,rt<<1|1,L,R,h,flag));
}
return ret;
}
int queryMAX(int l,int r,int rt,int L,int R,int h,int flag){
int mid=(l+r)>>1;
if(l==r){
if(flag){
if(treeMAX[rt]>=h)return l;
}else{
if(treeMIN[rt]<=h)return l;
}
return 0;
}
if(L<=l&&R>=r){
if(flag){
if(treeMAX[rt<<1|1]>=h)return queryMAX(mid+1,r,rt<<1|1,L,R,h,flag);
else if(treeMAX[rt<<1]>=h)return queryMAX(l,mid,rt<<1,L,R,h,flag);
}else{
if(treeMIN[rt<<1|1]<=h)return queryMAX(mid+1,r,rt<<1|1,L,R,h,flag);
else if(treeMIN[rt<<1]<=h)return queryMAX(l,mid,rt<<1,L,R,h,flag);
}
return 0;
}
int ret=0;
if(flag){
if(mid>=L&&treeMAX[rt<<1]>=h)ret=max(ret,queryMAX(l,mid,rt<<1,L,R,h,flag));
if(R>=mid+1&&treeMAX[rt<<1|1]>=h)ret=max(ret,queryMAX(mid+1,r,rt<<1|1,L,R,h,flag));
}else{
if(mid>=L&&treeMIN[rt<<1]<=h)ret=max(ret,queryMAX(l,mid,rt<<1,L,R,h,flag));
if(R>=mid+1&&treeMIN[rt<<1|1]<=h)ret=max(ret,queryMAX(mid+1,r,rt<<1|1,L,R,h,flag));
}
return ret;
}
int getUpDown(int x,int y){
int ans=0;
for(int j=mostL[x][y];j<=mostR[x][y];j++){
tmptree[j]=mostH[x][j];
}
build(mostL[x][y],mostR[x][y],1);
for(int i=1;i<=x;i++){
if(str[i][y]=='.')continue;
if((mostR[i][y]-mostL[i][y]+1)*(x-i+1)<=ans)continue;
int l=queryMIN(mostL[x][y],mostR[x][y],1,mostL[i][y],y,i,0);
int r=queryMAX(mostL[x][y],mostR[x][y],1,y,mostR[i][y],i,0);
ans=max(ans,(r-l+1)*(x-i+1));
}
for(int j=mostL[x][y];j<=mostR[x][y];j++){
tmptree[j]=mostD[x][j];
}
build(mostL[x][y],mostR[x][y],1);
for(int i=n;i>=x;i--){
if(str[i][y]=='.')continue;
if((mostR[i][y]-mostL[i][y]+1)*(i-x+1)<=ans)continue;
int l=queryMIN(mostL[x][y],mostR[x][y],1,mostL[i][y],y,i,1);
int r=queryMAX(mostL[x][y],mostR[x][y],1,y,mostR[i][y],i,1);
ans=max(ans,(r-l+1)*(i-x+1));
}
return ans;
}
int getLeftRight(int x,int y){
int ans=0;
for(int i=mostH[x][y];i<=mostD[x][y];i++){
tmptree[i]=mostL[i][y];
}
build(mostH[x][y],mostD[x][y],1);
for(int j=1;j<=y;j++){
if(str[x][j]=='.')continue;
if((mostD[x][j]-mostH[x][j]+1)*(y-j+1)<=ans)continue;
int l=queryMIN(mostH[x][y],mostD[x][y],1,mostH[x][j],x,j,0);
int r=queryMAX(mostH[x][y],mostD[x][y],1,x,mostD[x][j],j,0);
ans=max(ans,(r-l+1)*(y-j+1));
}
for(int i=mostH[x][y];i<=mostD[x][y];i++){
tmptree[i]=mostR[i][y];
}
build(mostH[x][y],mostD[x][y],1);
for(int j=m;j>=y;j--){
if(str[x][j]=='.')continue;
if((mostD[x][j]-mostH[x][j]+1)*(j-y+1)<=ans)continue;
int l=queryMIN(mostH[x][y],mostD[x][y],1,mostH[x][j],x,j,1);
int r=queryMAX(mostH[x][y],mostD[x][y],1,x,mostD[x][j],j,1);
ans=max(ans,(r-l+1)*(j-y+1));
}
return ans;
}
void pre(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(str[i][j]=='.'){
mostH[i][j]=mostL[i][j]=-1;
continue;
}
if(i==1){
mostH[i][j]=1;
}else{
if(str[i-1][j]=='#'){
mostH[i][j]=mostH[i-1][j];
}else{
mostH[i][j]=i;
}
}
if(j==1){
mostL[i][j]=1;
}else{
if(str[i][j-1]=='#'){
mostL[i][j]=mostL[i][j-1];
}else{
mostL[i][j]=j;
}
}
}
}
for(int i=n;i>=1;i--){
for(int j=m;j>=1;j--){
if(str[i][j]=='.'){
mostD[i][j]=mostR[i][j]=-1;
continue;
}
if(i==n){
mostD[i][j]=n;
}else{
if(str[i+1][j]=='#')mostD[i][j]=mostD[i+1][j];
else mostD[i][j]=i;
}
if(j==m){
mostR[i][j]=m;
}else{
if(str[i][j+1]=='#'){
mostR[i][j]=mostR[i][j+1];
}else{
mostR[i][j]=j;
}
}
}
}
}
void solve(){
pre();
int ty,x,y;
while(q--){
scanf("%d%d%d",&ty,&x,&y);
if(ty==1){
if(str[x][y]=='#') str[x][y]='.';
else str[x][y]='#';
changeUP(x,y);
changeDOWN(x,y);
changeLEFT(x,y);
changeRIGHT(x,y);
}else{
if(str[x][y]=='.'){
printf("0\n");
continue;
}
int ans=max(getUpDown(x,y),getLeftRight(x,y));
printf("%d\n",ans);
}
}
}
void init(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
scanf("%s",str[i]+1);
}
int main(){
int T=1;
scanf("%d",&T);
for(int kase=1;kase<=T;kase++){
init();
printf("Case #%d:\n",kase);
solve();
}
return 0;
}