xjb——洛谷P1191 矩形

https://www.luogu.org/problem/show?pid=1191
来一个用xjb算法的题解;
xjb是什么算法?
这种算法基本上可以解决所有题目;
也许你不会lct;
也许你不会插头dp;
也许你不会莫比乌斯反演;
但是,只要你会xjb算法,noip甚至省选noi都不成问题!

我们对于这道题
要有一个初步的想法;
对于(i,j)这个点;
如果可以求出以这个点为右下角的所有矩阵;
那么这道题就好办了;
但是这个类似与dp的思想,却好像无法实现;
那怎么办呢?
我们对于(i,j)
维护x表示这个点向左最多连续几个W
维护y表示这个点向上最多连续几个W
显然(i,j)这个点最大贡献就是x*y
但是我们咋么求这个点的实际贡献呢?
我们从x*y这个矩阵的左下角开始向右上角搜索;
勾出一条边界线;
边界线左下放全部是W
这样我们一遍勾出边界,一边计算答案就好了;
时间复杂度
150*150*300

#include<bits/stdc++.h>
using namespace std;
const int N=155;
int a[N][N],x[N][N],y[N][N],s[N][N];
int ans,n,m,xx,yy;
char c;
bool check(int x,int y,int xx,int yy){
    return (s[xx][yy]-s[xx][y-1]-s[x-1][yy]+s[x-1][y-1])==(xx-x+1)*(yy-y+1);
}
int dfs(int a1,int a2,int xx,int yy){
    int ans=0;
    int x=xx;
    int y=yy-a1+1;
    while(a1&&a2){
        ans+=a1;
        while(!check(x-1,y,xx,yy))y+=1,a1--;
        x-=1;
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){cin>>c;if(c=='W')a[i][j]=1;s[i][j]=a[i][j];}
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)s[i][j]+=s[i][j-1];
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)s[i][j]+=s[i-1][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(a[i][j]){
                x[i][j]=x[i][j-1]+1;
                y[i][j]=y[i-1][j]+1;
                ans+=dfs(x[i][j],y[i][j],i,j);
            }
    printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值