제출 #1078582

#제출 시각아이디문제언어결과실행 시간메모리
1078582myst6축구 경기장 (IOI23_soccer)C++17
0 / 100
4524 ms60228 KiB
#include <bits/stdc++.h>

using namespace std;

bool dp[4][2005][2005];

/*

let's consider the bottom edge
we must be able to reach all other cells with an up kick then left kick

a rectangle is a valid field because yes
if any two filled positions on same row or col have a tree between them then no

if we fill in all empty spaces and consider that whole square
we see that the trees form either strict decreasing or strict increasing thingies

xx..
xxx.
.xxx
..xx

still bad
consider top-left one
it needs to either have access to all rows or all cols

xxxx
xxxx
.xxx
..xx

now good

xxxx
.xxx
..xx
....

still good

so, one side needs to be completely filled in
if we can solve where the top side is completely full, then rotate 90deg 4 times

xxxx
.xxx
..xx
...x

now, restriction on rest is?
it must be increasing then decreasing section 

xxxxxxxx
.xxxxx.x
..xxx..x
...xx..x

let's say we have down[i][j] : how far down we can go from here
for a given row, let's say position k is the local maximum
then we do a greedy on both sides to calculate scores
so O(n^2) per row

so O(n^3) in total

can we ternary search the local maximum?


*/

const int MAXN = 2000;

int down[MAXN][MAXN];

int solve(int N, vector<vector<int>> F) {
    for (int i=0; i<N; i++) {
        for (int j=0; j<N; j++) {
            // go as far down as possible in O(n^3)
            for (int k=i; k<N; k++) {
                if (F[k][j] == 1) break;
                down[i][j] = k-i+1;
            }
        }
    }
    int best = 0;
    for (int i=0; i<N; i++) {
        for (int j=0; j<N; j++) {
            if (F[i][j] == 1) continue;
            // choose position (i, j) as the splitting point on row i
            int ans = down[i][j];
            // go left
            {
                int curr = down[i][j];
                for (int k=j-1; k>=0; k--) {
                    if (F[i][k] == 1) break;
                    curr = min(curr, down[i][k]);
                    ans += curr;
                }
            }
            // go right
            {
                int curr = down[i][j];
                for (int k=j+1; k<N; k++) {
                    if (F[i][k] == 1) break;
                    curr = min(curr, down[i][k]);
                    ans += curr;
                }
            }
            best = max(best, ans);
        }
    }
    return best;
}

vector<vector<int>> rotate(int N, vector<vector<int>> F) {
    vector<vector<int>> G(N, vector<int>(N));
    for (int i=0; i<N; i++) {
        for (int j=0; j<N; j++) {
            G[i][j] = F[N-1-j][i];
        }
    }
    return G;
}

int biggest_stadium(int N, vector<vector<int>> F) {
    int best = 0;
    for (int i=0; i<4; i++) {
        best = max(best, solve(N, F));
        F = rotate(N, F);
    }
    return best;
}

/*

5
0 0 0 0 0
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0

*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...