2018-acmicpc-asia-nakhon-pathom-regional-contest -- Problem L Largest Allowed Area(暴力二分检验+高级读入挂)

题目链接:没有
题目大意:

一个公司想买一块正方形的地建总部,奈何地皮到处有森林,公司无奈下决定,只好买一块正方型地,它最多含有一处森林,而且公司有的是钱,越大越好。

解题思路:
先维护一个二位前缀和数组记录1的和,行和列的范围都是1000,有T组数据,如果暴力遍历每个点,检验一个点时二分枚举边界长度,时间复杂度是O(T*(n^2) * log(n)),最大要跑2e8的数据。比赛时用scanf一直超时。比赛后试用一般的读入挂也超时,最后用了高级读入挂才AC,跑了0.4s.

代码如下:

#include<bits/stdc++.h>
using namespace std;

namespace fastIO {
    #define BUF_SIZE 100000
    //fread -> read
    bool IOerror = 0;
    inline char nc() {
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
        if(p1 == pend) {
            p1 = buf;
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);
            if(pend == p1) {
                IOerror = 1;
                return -1;
            }
        }
        return *p1++;
    }
    inline bool blank(char ch) {
        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
    }
    inline void read(int &x) {
        char ch;
        while(blank(ch = nc()));
        if(IOerror) return;
        for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
    }
    #undef BUF_SIZE
};
using namespace fastIO;

int sum[1005][1005], a[1005][1005];

int max(int x, int y){
    return x > y ? x : y;
}

int min(int x, int y){
    return x < y ? x : y;
}

int func(int x, int y, int s){
    int l = 1, r = s, mid = (l+r)/2, ans = 1;
    while(r >= l){
        mid = (l+r)/2;
        if((sum[x][y]-sum[x-mid][y]-sum[x][y-mid]+sum[x-mid][y-mid] <= 1) ) l = mid+1, ans = mid;
        else r = mid-1;
    }
    return ans;
}
int main()
{
    int t, n, m;
    read(t);
    while(t--){
        read(n);  read(m);
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                read(a[i][j]);
            }
        }
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
            }
        }
        int ans = 0;
        for(int i=1;i<=n;++i){
            for(int j=1;j<=m;++j){
                int d = min(i, j);
                ans = max(ans, func(i, j, d));
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值