제출 #766950

#제출 시각아이디문제언어결과실행 시간메모리
766950t6twotwoRectangles (IOI19_rect)C++17
59 / 100
5092 ms635380 KiB
#include "rect.h"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
vector<int> ms(vector<int> &a, bool f) {
    int n = a.size();
    vector<int> b(n, f ? n : -1), stk;
    for (int i = (f ? n - 1 : 0); i != (f ? -1 : n); i += (f ? -1 : 1)) {
        while (!stk.empty() && a[stk.back()] < a[i]) {
            stk.pop_back();
        }
        if (!stk.empty()) {
            b[i] = stk.back();
        }
        stk.push_back(i);
    }
    return b;
}
int lg[2501];
struct sparse_table {
    int n, e;
    int (*f)(int, int);
    vector<vector<int>> st;
    sparse_table() {
    }
    sparse_table(vector<int> &a, int (*_f)(int, int), int _e) : n(a.size()), f(_f), e(_e) {
        st = vector(n, vector<int>(lg[n] + 1, e));
        for (int i = 0; i < n; i++) {
            st[i][0] = a[i];
        }
        for (int j = 0; j < lg[n]; j++) {
            for (int i = 0; i + (2 << j) <= n; i++) {
                st[i][j + 1] = f(st[i][j], st[i + (1 << j)][j]);
            }
        }
    }
    int query(int l, int r) {
        if (l == r) {
            return e;
        }
        int k = lg[r - l];
        return f(st[l][k], st[r - (1 << k)][k]);
    }
};
int fmin(int x, int y) {
    return min(x, y);
}
int fmax(int x, int y) {
    return max(x, y);
}
ll count_rectangles(vector<vector<int>> a) {
    for (int i = 2; i <= 2500; i++) {
        lg[i] = lg[i / 2] + 1;
    }
    int n = a.size();
    int m = a[0].size();
    int ans = 0;
    auto solve = [&](int eq) {
        vector L(n, vector<int>(m));
        vector R(n, vector<int>(m));
        vector D(n, vector<int>(m));
        vector U(n, vector<int>(m));
        for (int i = 0; i < n; i++) {
            L[i] = ms(a[i], 0);
            R[i] = ms(a[i], 1);
        }
        for (int j = 0; j < m; j++) {
            vector<int> v(n);
            for (int i = 0; i < n; i++) {
                v[i] = a[i][j];
            }
            auto u = ms(v, 0);
            auto d = ms(v, 1);
            for (int i = 0; i < n; i++) {
                U[i][j] = u[i];
                D[i][j] = d[i];
            }
        }
        vector T(n, vector<vector<int>>(m));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (U[i][j] != -1) {
                    T[U[i][j]][j].push_back(i);
                }
            }
        }
        vector DL(n, vector<int>(m));
        vector DR(n, vector<int>(m));
        vector UL(n, vector<int>(m));
        vector UR(n, vector<int>(m));
        vector LD(n, vector<int>(m));
        vector LU(n, vector<int>(m));
        vector RD(n, vector<int>(m));
        vector RU(n, vector<int>(m));
        for (int j = 1; j < m - 1; j++) {
            vector<int> vl(n), vr(n);
            for (int i = 0; i < n; i++) {
                vl[i] = L[i][j + 1];
                vr[i] = R[i][j - 1];
            }
            sparse_table sl(vl, fmax, -1);
            sparse_table sr(vr, fmin, m);
            for (int i = 0; i < n; i++) {
                if (i + 1 < n - 1 && D[i][j] != n) {
                    DL[i][j] = sl.query(i + 1, D[i][j]);
                    DR[i][j] = sr.query(i + 1, D[i][j]);
                }
                if (i - 1 > 0 && U[i][j] != -1) {
                    UL[i][j] = sl.query(U[i][j] + 1, i);
                    UR[i][j] = sr.query(U[i][j] + 1, i);
                }
            }
        }
        for (int i = 1; i < n - 1; i++) {
            vector<int> vu(m), vd(m);
            for (int j = 0; j < m; j++) {
                vu[j] = U[i + 1][j];
                vd[j] = D[i - 1][j];
            }
            sparse_table su(vu, fmax, -1);
            sparse_table sd(vd, fmin, n);
            for (int j = 0; j < m; j++) {
                if (j + 1 < m - 1 && R[i][j] != m) {
                    RU[i][j] = su.query(j + 1, R[i][j]);
                    RD[i][j] = sd.query(j + 1, R[i][j]);
                }
                if (j - 1 > 0 && L[i][j] != -1) {
                    LU[i][j] = su.query(L[i][j] + 1, j);
                    LD[i][j] = sd.query(L[i][j] + 1, j);
                }
            }
        }
        auto check = [&](int x1, int y1, int x2, int y2) {
            if (x1 > x2 || y1 > y2 || x1 < 1 || y1 < 1 || x2 >= n - 1 || y2 >= m - 1) {
                return 0;
            }
            assert(R[x1][y1 - 1] == y2 + 1);
            if (a[x1][y1 - 1] <= a[x1][y2 + 1]) {
                if (R[x1][y1 - 1] != y2 + 1) {
                   return 0;
                }
                if (RD[x1][y1 - 1] <= x2) {
                    return 0;
                }
            }
            if (a[x2][y1 - 1] <= a[x2][y2 + 1]) {
                if (R[x2][y1 - 1] != y2 + 1) {
                    return 0;
                }
                if (RU[x2][y1 - 1] >= x1) {
                    return 0;
                }
            }
            if (a[x2][y1 - 1] >= a[x2][y2 + 1]) {
                if (L[x2][y2 + 1] != y1 - 1) {
                    return 0;
                }
                if (LU[x2][y2 + 1] >= x1) {
                    return 0;
                }
            }
            if (a[x1 - 1][y1] <= a[x2 + 1][y1]) {
                if (D[x1 - 1][y1] != x2 + 1) {
                    return 0;
                }
                if (DR[x1 - 1][y1] <= y2) {
                    return 0;
                }
            }
            if (a[x1 - 1][y1] >= a[x2 + 1][y1]) {
                if (U[x2 + 1][y1] != x1 - 1) {
                    return 0;
                }
                if (UR[x2 + 1][y1] <= y2) {
                    return 0;
                }
            }
            if (a[x1 - 1][y2] <= a[x2 + 1][y2]) {
                if (D[x1 - 1][y2] != x2 + 1) {
                    return 0;
                }
                if (DL[x1 - 1][y2] >= y1) {
                    return 0;
                }
            }
            if (a[x1 - 1][y2] >= a[x2 + 1][y2]) {
                if (U[x2 + 1][y2] != x1 - 1) {
                    return 0;
                }
                if (UL[x2 + 1][y2] >= y1) {
                    return 0;
                }
            }
            return 1;
        };
        for (int i = 1; i < n - 1; i++) {
            for (int j = 1; j < m - 1; j++) {
                int y = R[i][j - 1] - 1;
                if (y != m - 1 && (eq || a[i][j - 1] != a[i][y + 1])) {
                    int x = D[i - 1][j] - 1;
                    if (x != n - 1) {
                        ans += check(i, j, x, y);
                    }
                    for (int k : T[i - 1][j]) {
                        if (a[i - 1][j] != a[k][j]) {
                            ans += check(i, j, k - 1, y);
                        }
                    }
                }
            }
        }
    };
    solve(1);
    for (int i = 0; i < n; i++) {
        reverse(a[i].begin(), a[i].end());
    }
    solve(0);
    return ans;
}

컴파일 시 표준 에러 (stderr) 메시지

rect.cpp: In constructor 'sparse_table::sparse_table(std::vector<int>&, int (*)(int, int), int)':
rect.cpp:22:11: warning: 'sparse_table::f' will be initialized after [-Wreorder]
   22 |     int (*f)(int, int);
      |           ^
rect.cpp:21:12: warning:   'int sparse_table::e' [-Wreorder]
   21 |     int n, e;
      |            ^
rect.cpp:26:5: warning:   when initialized here [-Wreorder]
   26 |     sparse_table(vector<int> &a, int (*_f)(int, int), int _e) : n(a.size()), f(_f), e(_e) {
      |     ^~~~~~~~~~~~
#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...