Submission #143719

#TimeUsernameProblemLanguageResultExecution timeMemory
143719qkxwsmRectangles (IOI19_rect)C++14
72 / 100
5104 ms172424 KiB
#include "rect.h" #include <bits/stdc++.h> using namespace std; template<class T, class U> void ckmin(T &a, U b) { if (a > b) a = b; } template<class T, class U> void ckmax(T &a, U b) { if (a < b) a = b; } #define y1 qkx #define y2 wsm #define MP make_pair #define PB push_back #define LB lower_bound #define UB upper_bound #define fi first #define se second #define FOR(i, a, b) for (auto i = (a); i < (b); i++) #define FORD(i, a, b) for (auto i = (a) - 1; i >= (b); i--) #define SZ(x) ((int) (x).size()) #define ALL(x) (x).begin(), (x).end() #define INF 1000000007 #define MAXN 2513 typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; typedef vector<int> vi; typedef vector<ll> vl; typedef vector<pii> vpi; typedef vector<pll> vpl; int N, M; vector<vi> grid; int rt[MAXN][MAXN], dn[MAXN][MAXN], lt[MAXN][MAXN], up[MAXN][MAXN]; int pref[MAXN][MAXN]; bool subtask6 = true; vector<vector<vi> > col, row; set<pii> edges; ll ans; int psum(int x1, int x2, int y1, int y2) { return pref[x2 + 1][y2 + 1] - pref[x1][y2 + 1] - pref[x2 + 1][y1] + pref[x1][y1]; } ll count_rectangles(vector<vi> a) { N = SZ(a); M = SZ(a[0]); grid = a; FOR(i, 0, N) FOR(j, 0, M) if (grid[i][j] > 1) subtask6 = false; if (subtask6) { FOR(i, 0, N) { FOR(j, 0, M) { pref[i + 1][j + 1] = pref[i][j + 1] + pref[i + 1][j] - pref[i][j] + grid[i][j]; } } //for each square, compute the next 1 on the right FOR(i, 0, N) { rt[i][M] = M; FORD(j, M, 0) { rt[i][j] = (grid[i][j] ? j : rt[i][j + 1]); } } FOR(i, 0, M) { dn[N][i] = N; FORD(j, N, 0) { dn[j][i] = (grid[j][i] ? j : dn[j + 1][i]); } } FOR(x1, 1, N) { FOR(y1, 1, M) { if (grid[x1][y1]) continue; int y2 = rt[x1][y1] - 1, x2 = dn[x1][y1] - 1; if (x2 == N - 1 || y2 == M - 1) continue; // cerr << "CONSIDER " << x1 << ' ' << y1 << " -> " << x2 << ' ' << y2 << endl; if (psum(x1, x2, y1, y2) != 0) continue; if (psum(x1 - 1, x1 - 1, y1, y2) != (y2 - y1 + 1)) continue; if (psum(x2 + 1, x2 + 1, y1, y2) != (y2 - y1 + 1)) continue; if (psum(x1, x2, y1 - 1, y1 - 1) != (x2 - x1 + 1)) continue; if (psum(x1, x2, y2 + 1, y2 + 1) != (x2 - x1 + 1)) continue; ans++; } } } else { //BE SUPER CAREFUL ABOUT EQUALITY CASE. //for each guy, find the next guy right of it that's greater th an it. //ok fix the starting column #. FOR(i, 0, N) { vpi cand; cand.PB({INF, M}); FORD(j, M, 0) { while(cand.back().fi < grid[i][j]) cand.pop_back(); rt[i][j] = cand.back().se; cand.PB({grid[i][j], j}); } cand.clear(); cand.PB({INF, -1}); FOR(j, 0, M) { while(cand.back().fi < grid[i][j]) cand.pop_back(); lt[i][j] = cand.back().se; cand.PB({grid[i][j], j}); } } FOR(i, 0, M) { vpi cand; cand.PB({INF, N}); FORD(j, N, 0) { while(cand.back().fi < grid[j][i]) cand.pop_back(); dn[j][i] = cand.back().se; cand.PB({grid[j][i], j}); } cand.clear(); cand.PB({INF, -1}); FOR(j, 0, N) { while(cand.back().fi < grid[j][i]) cand.pop_back(); up[j][i] = cand.back().se; cand.PB({grid[j][i], j}); } } // FOR(i, 0, N) // { // FOR(j, 0, M) // { // cerr << up[i][j] << ' '; // } // cerr << endl; // } FOR(i, 0, N - 1) { edges.clear(); FOR(j, 0, M) { if (lt[i + 1][j] != -1 && lt[i + 1][j] < j - 1) edges.insert({lt[i + 1][j], j}); if (rt[i + 1][j] != M && rt[i + 1][j] > j + 1) edges.insert({j, rt[i + 1][j]}); } // cerr << "FROM ROW " << i << endl; FOR(j, i + 2, N) { //find all edges which they share in common. // cerr << "ROWS " << i << " -> " << j << endl; // cerr << "EDGES\n"; // for (pii p : edges) // { // cerr << p.fi << ' ' << p.se << endl; // } vpi ks; FOR(k, 0, M) { if (dn[i][k] == j || up[j][k] == i) { // cerr << "HI\n"; if (ks.empty() || ks.back().se != k - 1) { ks.PB({k, k}); } else { ks.back().se++; } // cerr << "BYE\n"; } } // cerr << "KS\n"; // for (pii p : ks) // { // cerr << p.fi << ',' << p.se << endl; // } for (pii p : ks) { for (pii q : edges) { if (p.fi <= q.fi + 1 && q.se - 1 <= p.se) { // cerr << "YAY " << i << ' ' << j << ' ' << q.fi << ' ' << q.se << endl; ans++; } } } for (auto it = edges.begin(); it != edges.end(); ) { int x = it -> fi, y = it -> se; if (rt[j][x] != y && lt[j][y] != x) it = edges.erase(it); else it++; } //ok now find these ranges. } } } 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...