Hướng dẫn giải của VM 09 Bài 08 - Giá trị chiếc quạt mo


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

Code mẫu của flashmt

#include <iostream>
#include <algorithm>
#include <cstdio>
#define oo 1000111222
#define fr(a,b,c) for (a=b;a<=c;a++)
#define frr(a,b,c) for (a=b;a>=c;a--)
using namespace std;

int m,n,k,re,a[333][333],Col_Min[333][333],Col_Max[333][333],Bot_Right[333][333],Top_Left[333][333];

void calc(int f[333][333])
{
    int i,h,j;
    fr(i,1,m)
        frr(h,i,1)
        {
            fr(j,1,n)
            {
                Col_Min[i][j]=min(Col_Min[i][j],a[h][j]);
                Col_Max[i][j]=max(Col_Max[i][j],a[h][j]);
                if (Col_Max[i][j]-Col_Min[i][j]>k) continue;
                int jj=j-1, Max=Col_Max[i][j], Min=Col_Min[i][j];
                while (jj && max(Max,Col_Max[i][jj])-min(Min,Col_Min[i][jj])<=k) 
                {
                    Max=max(Max,Col_Max[i][jj]);
                    Min=min(Min,Col_Min[i][jj]);
                    jj--;
                }
                f[i][j]=max(f[i][j],(i-h+1)*(j-jj));
            }
        }
    fr(i,1,m) fr(j,1,n) f[i][j]=max(f[i][j],max(f[i][j-1],f[i-1][j]));
}

void Reverse()
{
    int i,j;
    fr(i,1,(m+1)/2) 
        fr(j,1,(i*2<=m?n:n/2))
        {
            int t=a[i][j];
            a[i][j]=a[m+1-i][n+1-j];
            a[m+1-i][n+1-j]=t;
        }
}

int main()
{
    int i,j;
    cin >> m >> n >> k;
    fr(i,1,m) fr(j,1,n) scanf("%d",&a[i][j]);

    fr(i,1,m) fr(j,1,n) Col_Min[i][j]=Col_Max[i][j]=a[i][j];
    calc(Bot_Right);

    Reverse();
    fr(i,1,m) fr(j,1,n) Col_Min[i][j]=Col_Max[i][j]=a[i][j];
    calc(Top_Left);

    fr(i,1,m) fr(j,1,n)
    {
        if (i<m) re=max(re,Bot_Right[i][j]+Top_Left[m-i][n]);
        if (j<n) re=max(re,Bot_Right[i][j]+Top_Left[m][n-j]);
    }
    cout << re << endl;
    return 0;
}

Code mẫu của ladpro98

program BLAND;
uses
    math;
const
    MAXN = 303;
    INFINTY = trunc(2e9);
var
    m, n, maxDiff: longint;
    a, b: array[0..MAXN, 0..MAXN] of longint;
    minA, maxA, Q_max, Q_min, down, up: array[0..MAXN] of longint;

function sweep(row: longint): longint;
var
    l_max, l_min, r_max, r_min: longint;
    i, j: longint;
    answer: longint;
begin
    l_max := 1; l_min := 1;
    r_max := 0; r_min := 0;
    j := 1;
    answer := 0;
    for i := 1 to n do
    begin
        maxA[i] := max(maxA[i], a[row, i]);
        minA[i] := min(minA[i], a[row, i]);
        while (r_max >= l_max) and (maxA[Q_max[r_max]] <= maxA[i]) do dec(r_max);
        while (r_min >= l_min) and (minA[Q_min[r_min]] >= minA[i]) do dec(r_min);
        inc(r_max); Q_max[r_max] := i;
        inc(r_min); Q_min[r_min] := i;
        while (j <= i) and ((maxA[Q_max[l_max]] - minA[Q_min[l_min]]) > maxDiff) do
        begin
            inc(j);
            if (l_max <= r_max) and (Q_max[l_max] < j) then inc(l_max);
            if (l_min <= r_min) and (Q_min[l_min] < j) then inc(l_min);
        end;
        answer := max(answer, i - j + 1);
    end;
    exit(answer);
end;    

function solve(): longint;
var
    i, j: longint;
    current, answer: longint;
begin
    answer := 0;
    for i := 1 to m do
    begin
        up[i] := 0;
        down[i] := 0;
    end;
    for i := 1 to m do
    begin
        for j := 1 to n do
        begin
            maxA[j] := -INFINTY;
            minA[j] := INFINTY;
        end;
        for j := i to m do
        begin
            current := sweep(j) * (j - i + 1);
            down[i] := max(down[i], current);
            up[j] := max(up[j], current);
        end;
        for j := 2 to m do
        begin
            answer := max(answer, up[j - 1] + down[j]);
            up[j] := max(up[j], up[j - 1]);
        end;
    end;
    exit(answer);
end;

procedure rotate();
var
    save: longint;
    i, j: longint;
begin
    for i := 1 to m do for j := 1 to n do
        b[j, i] := a[i, j];
    save := m; m := n; n := save;
    for i := 1 to m do for j := 1 to n do
        a[i, j] := b[i, j];
end;

procedure main();
var
    i, j: longint;
    firstSolve, secondSolve: longint;
begin
    read(m, n, maxDiff);
    for i := 1 to m do for j := 1 to n do read(a[i, j]);
    firstSolve := solve();
    rotate();
    secondSolve := solve();
    writeln(max(firstSolve, secondSolve));
end;

begin
    main();
end.

Code mẫu của RR

#include <iostream>
#include <algorithm>
#define FOR(i,a,b)  for(int i=a; i<=b; i++)
#define FORD(i,a,b) for(int i=a; i>=b; i--)
#define MAXN 311
using namespace std;

int m,n,k;
int up_[MAXN],down_[MAXN],left_[MAXN],right_[MAXN];
int h[MAXN][MAXN];
int ln[10][10][MAXN][MAXN],nn[10][10][MAXN][MAXN];
int val[520];
int nhan[MAXN][MAXN];

void inp() {
    scanf("%d %d %d",&m,&n,&k);
    FOR(i,1,m)
    FOR(j,1,n)
        scanf("%d",&h[i][j]);
}

void RMQ() {
    FOR(i,1,m)
    FOR(j,1,n)
        ln[0][0][i][j]=nn[0][0][i][j]=h[i][j];

    FOR(lj,1,9)
        FOR(i,1,m)
        FOR(j,1,n-(1<<lj)+1) {
            ln[0][lj][i][j]=max(ln[0][lj-1][i][j],ln[0][lj-1][i][j+(1<<(lj-1))]);
            nn[0][lj][i][j]=min(nn[0][lj-1][i][j],nn[0][lj-1][i][j+(1<<(lj-1))]);
        }

    FOR(li,1,9)
        FOR(i,1,m-(1<<li)+1)
        FOR(j,1,n) {
            ln[li][0][i][j]=max(ln[li-1][0][i][j],ln[li-1][0][i+(1<<(li-1))][j]);
            nn[li][0][i][j]=min(nn[li-1][0][i][j],nn[li-1][0][i+(1<<(li-1))][j]);
        }

    FOR(li,1,9)
    FOR(lj,1,9)
        FOR(i,1,m-(1<<li)+1)
        FOR(j,1,n-(1<<lj)+1) {
            ln[li][lj][i][j]=max(ln[li][lj-1][i][j],ln[li][lj-1][i][j+(1<<(lj-1))]);
            nn[li][lj][i][j]=min(nn[li][lj-1][i][j],nn[li][lj-1][i][j+(1<<(lj-1))]);
        }
}

inline int get(int i1,int i2,int j1,int j2) {
    int ki=val[i2-i1+1];
    int kj=val[j2-j1+1];
    int tmp1=j2-(1<<kj)+1;
    int tmp2=i2-(1<<ki)+1;

    return max(max(ln[ki][kj][i1][j1],ln[ki][kj][i1][tmp1]),
               max(ln[ki][kj][tmp2][j1],ln[ki][kj][tmp2][tmp1]))
          -min(min(nn[ki][kj][i1][j1],nn[ki][kj][i1][tmp1]),
               min(nn[ki][kj][tmp2][j1],nn[ki][kj][tmp2][tmp1]));     
}

void init() {
    FOR(i,0,300)
    FOR(j,0,300)
        nhan[i][j]=i*j;
}

void solve() {
    FOR(i,0,9) val[1<<i]=i;
    FOR(i,2,511) if (!val[i]) val[i]=val[i-1];

    FOR(l,1,m)
    FOR(r,l,m) {
        int jj=1;
        FOR(j,1,n) {
            while (jj<=j && get(l,r,jj,j)>k) jj++;
            if (jj>j) continue;
            int now=nhan[r-l+1][j-jj+1];
            up_[l] >?= now;
            down_[r] >?= now;
            left_[j] >?= now;
            right_[jj] >?= now;
        }
    }

    FOR(i,2,m) down_[i] >?= down_[i-1];
    FORD(i,m-1,1) up_[i] >?= up_[i+1];

    FOR(i,2,n) left_[i] >?= left_[i-1];
    FORD(i,n-1,1) right_[i] >?= right_[i+1];

//    FOR(i,1,m) cout<<down_[i]<<" "<<up_[i]<<endl;
//    FOR(i,1,n) cout<<left_[i]<<" "<<right_[i]<<endl;

    int res=0;
    FOR(i,1,m-1) res >?= down_[i]+up_[i+1];
    FOR(i,1,n-1) res >?= left_[i]+right_[i+1];

    cout<<res;
}

int main() {
    inp();
    RMQ();
    init();
    solve();
    return 0;
}

Code mẫu của khuc_tuan

#include <cstdio>

#include <algorithm>

using namespace std;



int m, n, k, result;

int a[303][303], b[303][303];

int F[303][303], end[303], start[303];

int mm[303], MM[303];



pair<int,int> qmin[303], qmax[303];

int lmin, rmin, lmax, rmax;



void add(pair<int,int> p, pair<int,int> qmin[303], int &L, int &R) {

    while(L<=R && qmin[R] > p) --R;

    qmin[++R] = p;

}



void process() {

    memset( F, 0, sizeof(F));

    memset( start, 0, sizeof(start));

    memset( end, 0, sizeof(end));

    for(int i=0;i<m;++i) {

        memset( mm, 0x1f, sizeof(mm));

        memset( MM, 0xAF, sizeof(MM));

        for(int i2=i;i2<m;++i2) {

            int st = 0;

            lmin = lmax = 1;

            rmin = rmax = 0;

            for(int j=0;j<n;++j) {

                mm[j] <?= a[i2][j];

                MM[j] >?= a[i2][j];

                add( make_pair(mm[j], j), qmin, lmin, rmin);

                add( make_pair(-MM[j], j), qmax, lmax, rmax);

                for(;st <= j && -qmin[lmin].first-qmax[lmax].first > k;++st) {

                    if(qmin[lmin].second == st) ++lmin;

                    if(qmax[lmax].second == st) ++lmax;

                }   

                if(st <= j) F[i][i2] >?= j - st + 1;

            }

            start[i] >?= F[i][i2] * (i2 + 1 - i);

            end[i2] >?= F[i][i2] * (i2 + 1 - i);

        }

    }

    for(int i=1;i<m;++i) end[i] >?= end[i-1];

    for(int i=m-2;i>=0;--i) start[i] >?= start[i+1];

    for(int i=0;i+1<m;++i) result >?= end[i] + start[i+1];

}



int main() {

    scanf("%d%d%d", &m, &n, &k);

    for(int i=0;i<m;++i)

        for(int j=0;j<n;++j)

            scanf("%d", a[i] + j);



    process();

    for(int i=0;i<m;++i)

        for(int j=0;j<n;++j)

            b[j][i] = a[i][j];

    memmove( a, b, sizeof(a));

    swap(m,n);

    process();

    printf("%d\n", result);

    return 0;

}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.