2019 牛客多校训练营3 Planting Trees(RMQ预处理)

题解:

        很容易想到二维RMQ算法,但是常数实在是太大了,扣掉常数+算法减枝卡可以过。

        顺便给个读入挂。

#include<bits/stdc++.h>
using namespace std;
#define rei register int
const int MX = 505;
const int INF = 1e9;
namespace IO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
//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;}
            //{printf("IO error!\n");system("pause");for (;;);exit(0);}
        }
        return *p1++;
    }
    inline bool blank(char ch) {return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';}
    inline void read(int &x) {
        bool sign = 0; char ch = nc(); x = 0;
        for (; blank(ch); ch = nc());
        if (IOerror)return;
        if (ch == '-')sign = 1, ch = nc();
        for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0';
        if (sign)x = -x;
    }
    inline void read(ll &x) {
        bool sign = 0; char ch = nc(); x = 0;
        for (; blank(ch); ch = nc());
        if (IOerror)return;
        if (ch == '-')sign = 1, ch = nc();
        for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0';
        if (sign)x = -x;
    }
    inline void read(double &x) {
        bool sign = 0; char ch = nc(); x = 0;
        for (; blank(ch); ch = nc());
        if (IOerror)return;
        if (ch == '-')sign = 1, ch = nc();
        for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0';
        if (ch == '.') {
            double tmp = 1; ch = nc();
            for (; ch >= '0' && ch <= '9'; ch = nc())tmp /= 10.0, x += tmp * (ch - '0');
        }
        if (sign)x = -x;
    }
    inline void read(char *s) {
        char ch = nc();
        for (; blank(ch); ch = nc());
        if (IOerror)return;
        for (; !blank(ch) && !IOerror; ch = nc()) * s++ = ch;
        *s = 0;
    }
    inline void read(char &c) {
        for (c = nc(); blank(c); c = nc());
        if (IOerror) {c = -1; return;}
    }
//fwrite->write
    struct Ostream_fwrite {
        char *buf, *p1, *pend;
        Ostream_fwrite() {buf = new char[BUF_SIZE]; p1 = buf; pend = buf + BUF_SIZE;}
        void out(char ch) {
            if (p1 == pend) {
                fwrite(buf, 1, BUF_SIZE, stdout); p1 = buf;
            }
            *p1++ = ch;
        }
        void print(int x) {
            static char s[15], *s1; s1 = s;
            if (!x)*s1++ = '0';
            if (x < 0)out('-'), x = -x;
            while(x)*s1++ = x % 10 + '0', x /= 10;
            while(s1-- != s)out(*s1);
        }
        void println(int x) {
            static char s[15], *s1; s1 = s;
            if (!x)*s1++ = '0';
            if (x < 0)out('-'), x = -x;
            while(x)*s1++ = x % 10 + '0', x /= 10;
            while(s1-- != s)out(*s1); out('\n');
        }
        void print(ll x) {
            static char s[25], *s1; s1 = s;
            if (!x)*s1++ = '0';
            if (x < 0)out('-'), x = -x;
            while(x)*s1++ = x % 10 + '0', x /= 10;
            while(s1-- != s)out(*s1);
        }
        void println(ll x) {
            static char s[25], *s1; s1 = s;
            if (!x)*s1++ = '0';
            if (x < 0)out('-'), x = -x;
            while(x)*s1++ = x % 10 + '0', x /= 10;
            while(s1-- != s)out(*s1); out('\n');
        }
        void print(double x, int y) {
            static ll mul[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
                               1000000000, 10000000000LL, 100000000000LL, 1000000000000LL, 10000000000000LL,
                               100000000000000LL, 1000000000000000LL, 10000000000000000LL, 100000000000000000LL
            };
            if (x < -1e-12)out('-'), x = -x; x *= mul[y];
            ll x1 = (ll)floor(x);
            if (x - floor(x) >= 0.5)++x1;
            ll x2 = x1 / mul[y], x3 = x1 - x2 * mul[y]; print(x2);
            if (y > 0) {out('.'); for (size_t i = 1; i < y && x3 * mul[i] < mul[y]; out('0'), ++i); print(x3);}
        }
        void println(double x, int y) {print(x, y); out('\n');}
        void print(char *s) {while (*s)out(*s++);}
        void println(char *s) {while (*s)out(*s++); out('\n');}
        void flush() {if (p1 != buf) {fwrite(buf, 1, p1 - buf, stdout); p1 = buf;}}
        ~Ostream_fwrite() {flush();}
    } Ostream;
    inline void print(int x) {Ostream.print(x);}
    inline void println(int x) {Ostream.println(x);}
    inline void print(char x) {Ostream.out(x);}
    inline void println(char x) {Ostream.out(x); Ostream.out('\n');}
    inline void print(ll x) {Ostream.print(x);}
    inline void println(ll x) {Ostream.println(x);}
    inline void print(double x, int y) {Ostream.print(x, y);}
    inline void println(double x, int y) {Ostream.println(x, y);}
    inline void print(char *s) {Ostream.print(s);}
    inline void println(char *s) {Ostream.println(s);}
    inline void println() {Ostream.out('\n');}
    inline void flush() {Ostream.flush();}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
}

int n,m;

int a[MX][MX],lastl[MX];

int mind[MX][MX][11][11],maxd[MX][MX][11][11];
void init(){
    for(rei i = 1; i <= n; ++i){
        for(rei j = 1; j <= n; ++j){
            mind[i][j][0][0] = maxd[i][j][0][0] = a[i][j];
            for(rei k = 0; (1<<k) <= i; ++k){
                for(rei l = 0; (1<<l) <= j; ++l){
                    mind[i][j][k][l+1] = min(mind[i][j][k][l],mind[i][j-(1<<l)][k][l]);
                    maxd[i][j][k][l+1] = max(maxd[i][j][k][l],maxd[i][j-(1<<l)][k][l]);

                    mind[i][j][k+1][l] = min(mind[i][j][k][l],mind[i-(1<<k)][j][k][l]);
                    maxd[i][j][k+1][l] = max(maxd[i][j][k][l],maxd[i-(1<<k)][j][k][l]);
                }
            }
        }
    }
}

inline int check(rei x1, rei x2, rei y1, rei y2){
    int r = (int)(log2(double(x2-x1+1))), c = (int)(log2(double(y2-y1+1)));

    x1 += (1<<r) - 1;
    y1 += (1<<c) - 1;
    int maxx = max( max(maxd[x2][y2][r][c],maxd[x1][y2][r][c]), max(maxd[x1][y1][r][c], maxd[x2][y1][r][c]) );
    int minx = min( min(mind[x2][y2][r][c],mind[x1][y2][r][c]), min(mind[x1][y1][r][c], mind[x2][y1][r][c]) );

    return maxx - minx <= m;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
    int T;
    IO::read(T);
    while(T--){
        IO::read(n); IO::read(m);
        for(rei i = 1; i <= n; ++i){
            for(rei j = 1;  j <= n; ++j){
                IO::read(a[i][j]);
            }
        }
        init();

        int ans = 0;
        for(rei i = 1; i <= n; ++i){
            for(rei k = i; k >= 1; --k) lastl[k] = 1;

            for(rei j = 1; j <= n; ++j){
                int l = lastl[i];
                int st = min(i,i-ans/(j-l+1));
                for(rei k = st; k >= 1; --k) {
                    l = max(l,lastl[k]);
                    if((j-l+1)*i <= ans) break;
                    while(l <= j && !check(k,i,l,j)) l++;
                    lastl[k] = l;
                    if(l > j) break;

                    ans = max(ans,(i-k+1)*(j-l+1));
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值