Submission #1028949

#TimeUsernameProblemLanguageResultExecution timeMemory
1028949onbertRectangles (IOI19_rect)C++17
72 / 100
5085 ms1003140 KiB
#include "rect.h" #include <bits/stdc++.h> using namespace std; #define ss short #define ll long long struct range { ss r, mx; }; bool cmp0(range &a, range &b) {return a.r > b.r;} bool cmp1(range &a, range &b) {return a.mx > b.mx;} const int maxn = 2505, INF = 2505; int n, m; vector<vector<vector<pair<ss,ss>>>> pos[2]; vector<vector<vector<range>>> start[2]; ss fen[maxn]; void update(int id, int val) { while (id<maxn) { fen[id] += val; id += (id & -id); } } int qry(int id) { int val = 0; while (id >= 1) { val += fen[id]; id -= (id & -id); } return val; } pair<ss,ss> seg[10005]; void build(int id, int l, int r) { if (l==r) { seg[id] = {l, l}; return; } int mid = (l+r)/2; build(id*2, l, mid); build(id*2+1, mid+1, r); seg[id] = {min(seg[id*2].first, seg[id*2+1].first), max(seg[id*2].second, seg[id*2+1].second)}; } void update1(int id, int l, int r, int target) { if (r<target || target<l) return; if (l==r) { seg[id] = {INF, -1}; return; } int mid = (l+r)/2; update1(id*2, l, mid, target); update1(id*2+1, mid+1, r, target); seg[id] = {min(seg[id*2].first, seg[id*2+1].first), max(seg[id*2].second, seg[id*2+1].second)}; } ss qry1(int id, int l, int r, int findl, int findr, int t) { if (r<findl || findr<l) { if (t==0) return INF; else return -1; } if (findl<=l && r<=findr) { if (t==0) return seg[id].first; else return seg[id].second; } int mid = (l+r)/2; int lhs = qry1(id*2, l, mid, findl, findr, t), rhs = qry1(id*2+1, mid+1, r, findl, findr, t); if (t==0) return min(lhs, rhs); else return max(lhs, rhs); } long long count_rectangles(vector<vector<int32_t>> a) { n = a.size(), m = a[0].size(); pos[0].resize(m); for (int i=0;i<m;i++) pos[0][i].resize(m - i); pos[1].resize(n); for (int i=0;i<n;i++) pos[1][i].resize(n - i); start[0].resize(n); start[1].resize(n); for (int i=0;i<n;i++) start[0][i].resize(m), start[1][i].resize(m); vector<pair<int,int>> cur; vector<ss> temp; vector<pair<int,int>> link(m); for (int i=0;i<n;i++) { cur.clear(); for (int j=0;j<m;j++) cur.push_back({a[i][j], j}); sort(cur.begin(), cur.end()); build(1, 0, m-1); for (int j=0;j<m;j++) link[j] = {j-1, j+1}; temp.clear(); for (int j=0;j<m;j++) { auto [val, id] = cur[j]; if (j>0 && val!=cur[j-1].first) { for (int x:temp) { ss l = qry1(1, 0, m-1, 0, x, 1), r = INF; if (l>=0) r = link[l].second; if (l>=0 && r<m) { l++, r--; if (pos[0][l][r-l].size()==0 || pos[0][l][r-l].back().first!=i) { pos[0][l][r-l].push_back({i, -1}); start[0][i][l].push_back({r, -1}); } } } temp.clear(); } update1(1, 0, m-1, id); ss l = link[id].first, r = link[id].second; if (l>=0) link[l].second = r; if (r<m) link[r].first = l; temp.push_back(id); } } link.resize(n); for (int j=0;j<m;j++) { cur.clear(); for (int i=0;i<n;i++) cur.push_back({a[i][j], i}); sort(cur.begin(), cur.end()); build(1, 0, n-1); for (int i=0;i<n;i++) link[i] = {i-1, i+1}; temp.clear(); for (int i=0;i<n;i++) { auto [val, id] = cur[i]; if (i>0 && val!=cur[i-1].first) { for (int x:temp) { ss l = qry1(1, 0, n-1, 0, x, 1), r = INF; if (l>=0) r = link[l].second; if (l>=0 && r<n) { l++, r--; if (pos[1][l][r-l].size()==0 || pos[1][l][r-l].back().first!=j) { pos[1][l][r-l].push_back({j, -1}); start[1][l][j].push_back({r, -1}); } } } temp.clear(); } update1(1, 0, n-1, id); ss l = link[id].first, r = link[id].second; if (l>=0) link[l].second = r; if (r<n) link[r].first = l; temp.push_back(id); } } for (int I=0;I<=1;I++) { int nn = m; if (I==1) nn = n; for (int l=0;l<nn;l++) for (int r=l;r<nn;r++) { sort(pos[I][l][r-l].begin(), pos[I][l][r-l].end()); int sz = pos[I][l][r-l].size(); for (int i=sz-1;i>=0;i--) { if (i==sz-1 || pos[I][l][r-l][i+1].first!=pos[I][l][r-l][i].first+1) pos[I][l][r-l][i].second = pos[I][l][r-l][i].first; else pos[I][l][r-l][i].second = pos[I][l][r-l][i+1].second; } } } for (int I=0;I<=1;I++) { for (int i=0;i<n;i++) for (int j=0;j<m;j++) { for (auto &[r, mx]:start[I][i][j]) { ss x = j, y = i; if (I==1) x = i, y = j; mx = (*lower_bound(pos[I][x][r-x].begin(), pos[I][x][r-x].end(), make_pair(y, (ss)-1))).second; } } } ll ans = 0; vector<int> LOG; for (int i=1;i<n-1;i++) for (int j=1;j<m-1;j++) { sort(start[0][i][j].begin(), start[0][i][j].end(), cmp0); sort(start[1][i][j].begin(), start[1][i][j].end(), cmp1); int pt = -1; LOG.clear(); for (auto [r, mx]:start[0][i][j]) { while (pt+1 < start[1][i][j].size() && start[1][i][j][pt+1].mx >= r) { pt++; update(start[1][i][j][pt].r, 1); LOG.push_back(start[1][i][j][pt].r); } ans += qry(mx); } for (int x:LOG) update(x, -1); } return ans; }

Compilation message (stderr)

rect.cpp: In function 'long long int count_rectangles(std::vector<std::vector<int> >)':
rect.cpp:171:25: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<range>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  171 |             while (pt+1 < start[1][i][j].size() && start[1][i][j][pt+1].mx >= r) {
      |                    ~~~~~^~~~~~~~~~~~~~~~~~~~~~~
#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...