제출 #1217099

#제출 시각아이디문제언어결과실행 시간메모리
1217099GabpRectangles (IOI19_rect)C++20
0 / 100
5128 ms637072 KiB
#include<bits/stdc++.h>
using namespace std;

const int N = 2500 + 5;
const int MX = 2;

struct SegTree {
    int st[4 * N];

    SegTree(int n) {
        for (int i = 0; i < 4 * n; i++) st[i] = 0;
    }

    void update(int v, int tl, int tr, int idx, int add) {
        if (tl == tr) {
            st[v] += add;
            return;
        }

        int mid = tl + (tr - tl) / 2;
        if (idx <= mid) update(2 * v, tl, mid, idx, add);
        else update(2 * v + 1, mid + 1, tr, idx, add);
        st[v] = st[2 * v] + st[2 * v + 1];
    }

    int query(int v, int tl, int tr, int l, int r) {
        if (l > r) return 0;
        if (tl == l && tr == r) return st[v];

        int mid = tl + (tr - tl) / 2;
        return query(2 * v, tl, mid, l, min(mid, r)) + query(2 * v + 1, mid + 1, tr, max(mid + 1, l), r);
    }
};

vector<pair<int,int>> sorted[MX];
set<int> col[N];
int row_order[N][N];
int row_order_cnt[N];
vector<int> col_has[N][N];
bool has[N][N];
pair<int,int> dp_row[N][N];
int dp_row_cnt[N];
int row_has[N][N];
int row_cnt[N];

long long int count_rectangles(vector<vector<int>> a) {
    int n = a.size(), m = a[0].size();
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) sorted[a[i][j]].push_back({i, j});
    }

    for (int i = 0; i < N; i++) {
        col[i].insert(-1);
        col[i].insert(n);
    }
    for (int i = 0; i < N; i++) row_order_cnt[i] = 0;
    for (int i = MX - 1; i >= 0; i--) {
        for (auto [x, y]: sorted[i]) {
            row_order[x][row_order_cnt[x]++] = y;
            col[y].insert(x);
        }

        for (auto [x, y]: sorted[i]) {
            auto it = col[y].find(x);
            
            it--;
            if (*it != -1 && *it < x - 1) {
                int l = (*it) + 1;
                int r = x - 1;
                if (col_has[l][y].empty() || col_has[l][y].back() > r) col_has[l][y].push_back(r);
            }

            it++;
            it++;
            if (*it != n && *it > x + 1) {
                int l = x + 1;
                int r = (*it) - 1;
                if (col_has[l][y].empty() || col_has[l][y].back() > r) col_has[l][y].push_back(r);
            }
        }
    }

    long long int ans = 0;
    SegTree st(m);
    for (int i = 0; i < m; i++) for (int j = 0; j < m; j++) has[i][j] = false;
    for (int i = 0; i < m; i++) row_cnt[i] = dp_row_cnt[i] = 0;

    for (int i = n - 2; i > 0; i--) {
        set<int> row;
        row.insert(-1);
        row.insert(m);

        int p = 0;
        while (p < m) {
            int curr = a[i][row_order[i][p]];
            int start = p;
            while (p < m && a[i][row_order[i][p]] == curr) {
                row.insert(row_order[i][p++]);
            }

            for (int j = start; j < p; j++) {
                int y = row_order[i][j];
                auto it = row.find(y);

                it--;
                if (*it != -1 && *it < y - 1) {
                    int l = (*it) + 1;
                    int r = y - 1;
                    row_has[l][row_cnt[l]++] = r;
                    has[l][r] = true;
                }

                it++;
                it++;
                if (*it != m && *it > y + 1) {
                    int l = y + 1;
                    int r = (*it) - 1;
                    row_has[l][row_cnt[l]++] = r;
                    has[l][r] = true;
                }
            }
        }

        vector<pair<int,int>> dp_col;
        for (int j = m - 2; j > 0; j--) {
            vector<pair<int,int>> ndp_col;
            int p1 = 0, p2 = 0;
            while (p1 < col_has[i][j].size() || p2 < dp_col.size()) {
                if (p1 == col_has[i][j].size()) p2++;
                else if (p2 == dp_col.size()) ndp_col.emplace_back(col_has[i][j][p1++], j);
                else if (col_has[i][j][p1] > dp_col[p2].first) ndp_col.emplace_back(col_has[i][j][p1++], j);
                else if (col_has[i][j][p1] < dp_col[p2].first) p2++;
                else {
                    p1++;
                    ndp_col.push_back(dp_col[p2++]);
                }
            }
            dp_col = move(ndp_col);

            vector<pair<int,int>> ndp_row;
            for (int id = 0; id < dp_row_cnt[j]; id++) {
                auto [x, y] = dp_row[j][id];
                if (!has[j][y]) continue;

                has[j][y] = false;
                ndp_row.emplace_back(x, y);
            }
            for (int x = 0; x < row_cnt[j]; x++) {
                int y = row_has[j][x];
                if (!has[j][y]) continue;

                has[j][y] = false;
                ndp_row.emplace_back(i, y);
            }
            dp_row_cnt[j] = ndp_row.size();
            for (int id = 0; id < ndp_row.size(); id++) dp_row[j][id] = ndp_row[id];
            row_cnt[j] = 0;

            int ptr = 0;
            for (auto [x, y]: dp_col) {
                while (ptr < dp_row_cnt[j] && dp_row[j][ptr].first >= x) {
                    st.update(1, 0, m - 1, dp_row[j][ptr++].second, 1);
                }

                ans += st.query(1, 0, m - 1, j, y);
            }
            while (--ptr >= 0) st.update(1, 0, m - 1, dp_row[j][ptr].second, -1);
        }
    }

    return ans;
}
#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...