Submission #322177

#TimeUsernameProblemLanguageResultExecution timeMemory
32217712tqianRectangles (IOI19_rect)C++17
72 / 100
5066 ms853916 KiB
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

#include "rect.h"
#include<bits/stdc++.h>
using namespace std;
using namespace std::chrono;
 
#define eb emplace_back
#define pb push_back
#define sz(x) int(x.size())
#define all(x) (x).begin(), (x).end()
 
template<class T> struct BIT {
    vector<T> bit;
    int n;
    
    void init(int n_) {
        n = n_;
        bit.resize(n);
    }
    
    T sum(int r) {
        T ret = 0;
        for (; r >= 0; r = (r & (r + 1)) - 1) ret += bit[r];
        return ret;
    }
    
    T sum(int l, int r) {
        return sum(r) - sum(l - 1);
    }
    
    void add(int idx, T delta) {
        for (; idx < n; idx = idx | (idx + 1)) bit[idx] += delta;
    }
};
 
struct seg { 
    short t;
    short l, r;
    short x, y;
    seg(short t_, short l_, short r_, short x_, short y_) {
        t = t_, l = l_, r = r_, x = x_, y = y_;
    }
};
 
long long count_rectangles(std::vector<std::vector<int> > a) {
    auto start = high_resolution_clock::now(); 
    int n = (int) a.size();
    int m = (int) a[0].size();
    vector<vector<pair<short, short>>> rows(n);
    vector<vector<pair<short, short>>> cols(m);
    for (int i = 0; i < n; i++) {
        vector<int> stk;
        for (int j = 0; j < m; j++) {
            while (sz(stk) && a[i][stk.back()] < a[i][j]) {
                if (stk.back() + 2 <= j) 
                    rows[i].emplace_back(stk.back(), j);
                stk.pop_back();
            }
            if (sz(stk) && stk.back() + 2 <= j) 
                rows[i].emplace_back(stk.back(), j);    
            stk.push_back(j);
            while (sz(stk) >= 2 && a[i][stk[sz(stk) - 1]] == a[i][stk[sz(stk) - 2]]) {
                swap(stk[sz(stk) - 1], stk[sz(stk) - 2]);
                stk.pop_back();
            }
        }
    }
    for (int j = 0; j < m; j++) {
        vector<int> stk;
        for (int i = 0; i < n; i++) {
            while (sz(stk) && a[stk.back()][j] < a[i][j]) {
                if (stk.back() + 2 <= i) 
                    cols[j].emplace_back(stk.back(), i);
                stk.pop_back();
            }
            if (sz(stk) && stk.back() + 2 <= i) 
                cols[j].emplace_back(stk.back(), i);
            stk.push_back(i);
            while (sz(stk) >= 2 && a[stk[sz(stk) - 1]][j] == a[stk[sz(stk) - 2]][j]) {
                swap(stk[sz(stk) - 1], stk[sz(stk) - 2]);
                stk.pop_back();
            }
        }
    }
    vector<vector<vector<seg>>> vert_corner(n + 5, vector<vector<seg>>(m + 5));
    vector<vector<pair<short, short>>> vert(m, vector<pair<short, short>>(m, {(short) -1, (short) -1}));
    for (int i = 0; i < n; i++) {
        for (auto bar : rows[i]) {
            if (vert[bar.first][bar.second].first == -1) {
                vert[bar.first][bar.second] = {i, i};
            } else {
                if (vert[bar.first][bar.second].second + 1 == i) {
                    vert[bar.first][bar.second].second++;
                } else {
                    int lo = vert[bar.first][bar.second].first;
                    int hi = vert[bar.first][bar.second].second;
                    for (int z = lo - 1; z <= hi + 1; z++) 
                        vert_corner[z + 1][bar.first + 1].emplace_back(1, bar.first + 1, bar.second + 1, lo, hi + 2);
                    vert[bar.first][bar.second] = {i, i};
                }
            }
        }
        if (i == n - 1) {
            for (int x = 0; x < m; x++) {
                for (int y = 0; y < m; y++) {
                    if (vert[x][y].first == -1) continue;
                    int lo = vert[x][y].first; 
                    int hi = vert[x][y].second;
                    for (int z = lo - 1; z <= hi + 1; z ++) 
                        vert_corner[z + 1][x + 1].emplace_back(1, x + 1, y + 1, lo, hi + 2);
                }
            }
        }
    }
    vector<vector<vector<seg>>> hori_corner(n + 5, vector<vector<seg>>(m + 5));
    vector<vector<pair<short, short>>> hori(n, vector<pair<short, short>>(n, {(short) -1, (short) -1}));
    for (int j = 0; j < m; j++) {
        for (auto bar : cols[j]) {
            if (hori[bar.first][bar.second].first == -1) {
                hori[bar.first][bar.second] = {j, j};
            } else {
                if (hori[bar.first][bar.second].second + 1 == j) {
                    hori[bar.first][bar.second].second++;
                } else {
                    int lo = hori[bar.first][bar.second].first;
                    int hi = hori[bar.first][bar.second].second;
                    for (int z = lo - 1; z <= hi + 1; z++) 
                        hori_corner[bar.first + 1][z + 1].emplace_back(0, bar.first + 1, bar.second + 1, lo, hi + 2);
                    hori[bar.first][bar.second] = {j, j};
                }
            }
        }
        if (j == m - 1) {
            for (int x = 0; x < n; x++) {
                for (int y = 0; y < n; y++) {
                    if (hori[x][y].first == -1) continue;
                    int lo = hori[x][y].first; 
                    int hi = hori[x][y].second;
                    for (int z = lo - 1; z <= hi + 1; z++) 
                        hori_corner[x + 1][z + 1].emplace_back(0, x + 1, y + 1, lo, hi + 2);           
                }
            }
        }
    }  
    // int cnt = 0;
    // for (auto x : hori_corner) for (auto y : x) for (auto z : x) cnt++;
    // for (auto x : vert_corner) for (auto y : x) for (auto z : x) cnt++;
    // cout << cnt << '\n';
    // auto stop = high_resolution_clock::now(); 

    // auto duration = duration_cast<microseconds>(stop - start); 
  
    // cout << "Time taken by function: "
         // << duration.count() << " microseconds" << endl; 
    long long ans = 0;
    BIT<short> B;
    B.init(n + 5);
    vector<array<short, 3>> segs;
    for (int i = 0; i < n + 5; i++) {
        for (int j = 0; j < m + 5; j++) {
            segs.clear();
            for (auto s : hori_corner[i][j]) {
                B.add(s.r, 1);
                segs.push_back({s.y, 1, s.r});
            }
            for (auto s : vert_corner[i][j]) 
                segs.push_back({s.r, 0, s.y});
            sort(segs.begin(), segs.end());
            for (auto s : segs) {
                if (s[1] == 1) {
                    B.add(s[2], -1);
                } else {
                    ans += B.sum(0, s[2]);
                }
            }
        }
    }
    // stop = high_resolution_clock::now(); 
    // duration = duration_cast<microseconds>(stop - start); 
  
    // cout << "Time taken by function: "
         // << duration.count() << " microseconds" << endl; 
	return ans;
}

Compilation message (stderr)

rect.cpp:2: warning: ignoring #pragma GCC optimization [-Wunknown-pragmas]
    2 | #pragma GCC optimization ("O3")
      | 
rect.cpp:3: warning: ignoring #pragma GCC optimization [-Wunknown-pragmas]
    3 | #pragma GCC optimization ("unroll-loops")
      | 
rect.cpp: In function 'long long int count_rectangles(std::vector<std::vector<int> >)':
rect.cpp:49:10: warning: variable 'start' set but not used [-Wunused-but-set-variable]
   49 |     auto start = high_resolution_clock::now();
      |          ^~~~~
#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...