Submission #439380

#TimeUsernameProblemLanguageResultExecution timeMemory
439380SortingRectangles (IOI19_rect)C++17
0 / 100
4 ms3532 KiB
#include "rect.h" #include <bits/stdc++.h> #pragma GCC optimize("O3") using namespace std; typedef long long ll; const int N = 2500 + 3; vector<vector<int>> a; int n, m; short u[N][N], d[N][N], l[N][N], r[N][N]; struct Min_Segment_Tree{ static constexpr short DEFAULT_VALUE = SHRT_MAX; short t[4 * N]; int merge(short l, short r){ return (l < r) ? l : r; } void init(short arr[], int i = 0, int l = 0, int r = m - 1){ if(l == r){ t[i] = arr[l]; return; } int mid = (l + r) >> 1; init(arr, 2 * i + 1, l, mid); init(arr, 2 * i + 2, mid + 1, r); t[i] = merge(t[2 * i + 1], t[2 * i + 2]); } int query(int sl, int sr, int i = 0, int l = 0, int r = m - 1){ if(sr < l || r < sl) return DEFAULT_VALUE; if(sl <= l && r <= sr) return t[i]; int mid = (l + r) >> 1; return merge(query(sl, sr, 2 * i + 1, l, mid), query(sl, sr, 2 * i + 2, mid + 1, r)); } }; struct Min_2D_Segment_Tree{ static constexpr short DEFAULT_VALUE = SHRT_MAX; Min_Segment_Tree t[4 * N]; int merge(short l, short r){ return (l < r) ? l : r; } void merge(Min_Segment_Tree &ret, Min_Segment_Tree &l, Min_Segment_Tree &r){ for(int i = 0; i < 4 * N; ++i) ret.t[i] = merge(l.t[i], r.t[i]); } void init(short arr[][N], int i = 0, int l = 0, int r = n - 1){ if(l == r){ t[i].init(arr[l]); return; } int mid = (l + r) >> 1; init(arr, 2 * i + 1, l, mid); init(arr, 2 * i + 2, mid + 1, r); merge(t[i], t[2 * i + 1], t[2 * i + 2]); } int query(int sl, int sr, int sl2, int sr2, int i = 0, int l = 0, int r = n - 1){ //cout << "query " << sl << " " << sr << " " << sl2 << " " << sr2 << " - " << i << " " << l << " " << r << endl; if(sr < l || r < sl) return DEFAULT_VALUE; if(sl <= l && r <= sr) return t[i].query(sl2, sr2); int mid = (l + r) >> 1; return merge(query(sl, sr, sl2, sr2, 2 * i + 1, l, mid), query(sl, sr, sl2, sr2, 2 * i + 2, mid + 1, r)); } }; struct Max_Segment_Tree{ static constexpr short DEFAULT_VALUE = SHRT_MIN; short t[4 * N]; int merge(short l, short r){ return (l > r) ? l : r; } void init(short arr[], int i = 0, int l = 0, int r = m - 1){ if(l == r){ t[i] = arr[l]; return; } int mid = (l + r) >> 1; init(arr, 2 * i + 1, l, mid); init(arr, 2 * i + 2, mid + 1, r); t[i] = merge(t[2 * i + 1], t[2 * i + 2]); } int query(int sl, int sr, int i = 0, int l = 0, int r = m - 1){ if(sr < l || r < sl) return DEFAULT_VALUE; if(sl <= l && r <= sr) return t[i]; int mid = (l + r) >> 1; return merge(query(sl, sr, 2 * i + 1, l, mid), query(sl, sr, 2 * i + 2, mid + 1, r)); } }; struct Max_2D_Segment_Tree{ static constexpr short DEFAULT_VALUE = SHRT_MIN; Max_Segment_Tree t[4 * N]; int merge(short l, short r){ return (l > r) ? l : r; } void merge(Max_Segment_Tree &ret, Max_Segment_Tree &l, Max_Segment_Tree &r){ for(int i = 0; i < 4 * N; ++i) ret.t[i] = merge(l.t[i], r.t[i]); } void init(short arr[][N], int i = 0, int l = 0, int r = n - 1){ if(l == r){ t[i].init(arr[l]); return; } int mid = (l + r) >> 1; init(arr, 2 * i + 1, l, mid); init(arr, 2 * i + 2, mid + 1, r); merge(t[i], t[2 * i + 1], t[2 * i + 2]); } int query(int sl, int sr, int sl2, int sr2, int i = 0, int l = 0, int r = n - 1){ //cout << "query " << sl << " " << sr << " " << sl2 << " " << sr2 << " - " << i << " " << l << " " << r << endl; if(sr < l || r < sl) return DEFAULT_VALUE; if(sl <= l && r <= sr) return t[i].query(sl2, sr2); int mid = (l + r) >> 1; return merge(query(sl, sr, sl2, sr2, 2 * i + 1, l, mid), query(sl, sr, sl2, sr2, 2 * i + 2, mid + 1, r)); } }; Max_2D_Segment_Tree u_st, l_st; Min_2D_Segment_Tree d_st, r_st; void init(){ stack<int> st; for(int j = 0; j < m; ++j){ for(int i = 0; i < n; ++i){ while(!st.empty() && a[i][j] > a[st.top()][j]){ d[st.top()][j] = i; st.pop(); } st.push(i); } while(!st.empty()){ d[st.top()][j] = n; st.pop(); } for(int i = n - 1; i >= 0; --i){ while(!st.empty() && a[i][j] > a[st.top()][j]){ u[st.top()][j] = i; st.pop(); } st.push(i); } while(!st.empty()){ u[st.top()][j] = -1; st.pop(); } } for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j){ while(!st.empty() && a[i][j] > a[i][st.top()]){ r[i][st.top()] = j; st.pop(); } st.push(j); } while(!st.empty()){ r[i][st.top()] = m; st.pop(); } for(int j = m - 1; j >= 0; --j){ while(!st.empty() && a[i][j] > a[i][st.top()]){ l[i][st.top()] = j; st.pop(); } st.push(j); } while(!st.empty()){ l[i][st.top()] = -1; st.pop(); } } } bool check(int x1, int y1, int x2, int y2){ return u_st.query(x1, x2, y1, y2) >= x1 - 1 && d_st.query(x1, x2, y1, y2) <= x2 + 1 && l_st.query(x1, x2, y1, y2) >= y1 - 1 && r_st.query(x1, x2, y1, y2) <= y2 + 1; } long long count_rectangles(vector<vector<int>> _a) { swap(a, _a); n = a.size(), m = a[0].size(); init(); u_st.init(u); d_st.init(d); r_st.init(r); l_st.init(l); ll ans = 0; vector<array<int, 4>> v; for(int x = 1; x < n - 1; ++x) for(int y = 1; y < m - 1; ++y) v.push_back({u[x][y] + 1, l[x][y] + 1, d[x][y] - 1, r[x][y] - 1}); sort(v.begin(), v.end()); v.resize(unique(v.begin(), v.end()) - v.begin()); for(auto [x1, y1, x2, y2]: v){ if(x1 <= 0 || y1 <= 0 || x2 >= n - 1 || y2 >= m - 1) continue; //cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl; ans += check(x1, y1, x2, y2); } 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...