2020秦皇岛CCPC 7-2 Bounding Wall(线段树)

维护每个点最左边/右边/上边的’.'位置
每次查询建立线段树然后枚举高度查找两边长度即可

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值