제출 #1322577

#제출 시각아이디문제언어결과실행 시간메모리
1322577SmuggingSpunRectangles (IOI19_rect)C++20
100 / 100
3968 ms620648 KiB
#include "rect.h" #include<bits/stdc++.h> using namespace std; typedef long long ll; template<class T>void maximize(T& a, T b){ if(a < b){ a = b; } } template<class T>void minimize(T& a, T b){ if(a > b){ a = b; } } vector<vector<int>>a; int n, m; namespace sub123{ bool check(int x, int y, int u, int v){ for(int i = x; i <= u; i++){ for(int j = y; j <= v; j++){ if(a[i][j] >= min(min(a[x - 1][j], a[u + 1][j]), min(a[i][y - 1], a[i][v + 1]))){ return false; } } } return true; } ll solve(){ int ans = 0; for(int x = 1; x < n; x++){ for(int y = 1; y < m; y++){ for(int u = x; u + 1 < n; u++){ for(int v = y; v + 1 < m; v++){ if(check(x, y, u, v)){ ans++; } } } } } return ans; } } namespace sub4{ const int lim = 702; int bit[lim], mxv[lim], bd[lim], bu[lim], rbd[lim], rbu[lim], up[lim][lim], down[lim][lim]; bitset<lim>can; vector<int>query[lim]; void update(int p){ for(p++; p < lim; p += p & -p){ bit[p]++; } } int get(int p){ int ans = 0; for(p++; p > 0; p -= p & -p){ ans += bit[p]; } return ans; } ll solve(){ for(int j = 0; j < m; j++){ vector<int>st; for(int i = 0; i < n; st.push_back(i++)){ while(!st.empty() && a[st.back()][j] < a[i][j]){ st.pop_back(); } up[i][j] = (st.empty() ? 0 : st.back()); } st.clear(); for(int i = n - 1; i > -1; st.push_back(i--)){ while(!st.empty() && a[st.back()][j] < a[i][j]){ st.pop_back(); } down[i][j] = (st.empty() ? n - 1 : st.back()); } } ll ans = 0; for(int l = 1; l < m; l++){ for(int i = 0; i < n; i++){ mxv[i] = bu[i] = can[i] = 0; } fill(bd, bd + n, n - 1); for(int r = l; r + 1 < m; r++){ for(int i = 0; i < n; i++){ maximize(mxv[i], a[i][r]); minimize(bd[i], down[i][r]); maximize(bu[i], up[i][r]); can[i] = mxv[i] < min(a[i][l - 1], a[i][r + 1]); } rbd[n - 1] = bd[n - 1]; for(int i = n - 2; i > -1; i--){ rbd[i] = !can[i + 1] ? i + 1 : rbd[i + 1]; } for(int i = n - 2; i > -1; i--){ query[min(rbd[i], bd[i])].push_back(i); } rbu[0] = bu[0]; for(int i = 1; i < n; i++){ rbu[i] = !can[i - 1] ? i - 1 : rbu[i - 1]; } memset(bit, 0, sizeof(bit)); for(int i = 1; i < n; i++){ update(max(bu[i], rbu[i])); for(int& j : query[i]){ ans += get(j) - j - 1; } query[i].clear(); } } } return ans; } } namespace sub5{ ll solve(){ int ans = 0; for(int l = 1; l < m; l++){ for(int r = l, mv = 0; r + 1 < m; r++){ maximize(mv, a[1][r]); if(a[1][r] >= min(a[0][r], a[2][r]) || mv >= a[1][l - 1]){ break; } if(mv < a[1][r + 1]){ ans++; } } } return ans; } } const int INF = 1e9; namespace sub6{ bool check_subtask(){ for(int i = 0; i < n; i++){ if(*max_element(a[i].begin(), a[i].end()) > 1){ return false; } } return true; } int cnt, min_x, max_x, min_y, max_y; void dfs(int x, int y){ if(x < 0 || x >= n || y < 0 || y >= m || a[x][y] == 1){ return; } cnt++; a[x][y] = 1; minimize(min_x, x); maximize(max_x, x); minimize(min_y, y); maximize(max_y, y); dfs(x - 1, y); dfs(x + 1, y); dfs(x, y - 1); dfs(x, y + 1); } ll solve(){ int ans = 0; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ if(a[i][j] == 0){ cnt = max_x = max_y = 0; min_x = min_y = INF; dfs(i, j); if(min_x > 0 && max_x + 1 < n && min_y > 0 && max_y + 1 < m && cnt == (max_x - min_x + 1) * (max_y - min_y + 1)){ ans++; } } } } return ans; } } namespace sub7{ const int lim = 2505; int bit[lim], beg[lim][lim], lst[lim][lim]; vector<pair<int, int>>row[lim][lim], col[lim][lim]; void update(int p, int x){ for(p++; p < lim; p += p & -p){ bit[p] += x; } } int get(int p){ int ans = 0; for(p++; p > 0; p -= p & -p){ ans += bit[p]; } return ans; } ll solve(){ memset(lst, 0x3f, sizeof(lst)); for(int i = 0; i < n; i++){ vector<int>st; for(int j = 0; j < m; st.push_back(j++)){ while(!st.empty() && a[i][st.back()] <= a[i][j]){ if(st.size() > 1 && a[i][st.back()] < a[i][j]){ int l = st[int(st.size()) - 2] + 1, r = j - 1; if(lst[l][r] + 1 != i){ beg[l][r] = i; } row[lst[l][r] = i][r].push_back(make_pair(beg[l][r], l)); } st.pop_back(); } } } memset(lst, 0x3f, sizeof(lst)); for(int j = 0; j < m; j++){ vector<int>st; for(int i = 0; i < n; st.push_back(i++)){ while(!st.empty() && a[st.back()][j] <= a[i][j]){ if(st.size() > 1 && a[st.back()][j] < a[i][j]){ int l = st[int(st.size()) - 2] + 1, r = i - 1; if(lst[l][r] + 1 != j){ beg[l][r] = j; } col[r][lst[l][r] = j].push_back(make_pair(l, beg[l][r])); } st.pop_back(); } } } ll ans = 0; memset(bit, 0, sizeof(bit)); for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ sort(row[i][j].begin(), row[i][j].end(), greater<pair<int, int>>()); sort(col[i][j].begin(), col[i][j].end(), greater<pair<int, int>>()); int p = 0; for(auto& [r1, c1] : row[i][j]){ while(p < col[i][j].size() && col[i][j][p].first >= r1){ update(col[i][j][p++].second, 1); } ans += get(c1); } while(p-- > 0){ update(col[i][j][p].second, -1); } } } return ans; } } ll count_rectangles(vector<vector<int>>_a){ swap(a, _a); if(min(n = a.size(), m = a[0].size()) < 3){ return 0; } if(max(n = a.size(), m = a[0].size()) <= 200){ return sub123::solve(); } if(n == 3){ return sub5::solve(); } if(max(n, m) <= 700){ return sub4::solve(); } if(sub6::check_subtask()){ return sub6::solve(); } return sub7::solve(); }
#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...