Submission #278515

#TimeUsernameProblemLanguageResultExecution timeMemory
278515KastandaRectangles (IOI19_rect)C++14
100 / 100
3420 ms403976 KiB
// M #include<bits/stdc++.h> #include "rect.h" #pragma GCC optimize("unroll-loops") #pragma GCC optimize("O3") using namespace std; const int N = 2505, MXN = N * N, LG = 13; int L[N][N], R[N][N], D[N][N], U[N][N], RMQ[LG][N], Log[N]; bool Cant[MXN]; vector < int > qL[N], qR[N], qU[N], qD[N]; vector < int > Gen(vector < int > A, int w = 0) { int k = (int)A.size(); vector < int > Rs(k); for (int i = 0; i < k; i ++) { Rs[i] = i - 1; while (Rs[i] >= 0 && A[Rs[i]] < A[i] + w) Rs[i] = Rs[Rs[i]]; } return Rs; } long long count_rectangles(vector < vector < int > > A) { int n = (int)A.size(); int m = (int)A[0].size(); for (int i = 0; i < n; i ++) { vector < int > temp, res; for (int j = 0; j < m; j ++) temp.push_back(A[i][j]); res = Gen(temp, 1); for (int j = 0; j < m; j ++) L[i][j] = res[j]; reverse(temp.begin(), temp.end()); res = Gen(temp, 1); for (int j = 0; j < m; j ++) R[i][j] = m - res[m - j - 1] - 1; } for (int j = 0; j < m; j ++) { vector < int > temp, res; for (int i = 0; i < n; i ++) temp.push_back(A[i][j]); res = Gen(temp, 1); for (int i = 0; i < n; i ++) U[i][j] = res[i]; reverse(temp.begin(), temp.end()); res = Gen(temp, 1); for (int i = 0; i < n; i ++) D[i][j] = n - res[n - i - 1] - 1; } vector < tuple < int , int , int , int > > Cands; for (int i = 0; i < n; i ++) for (int j = 0; j < m; j ++) if (L[i][j] >= 0 && R[i][j] < m && U[i][j] >= 0 && D[i][j] < n) Cands.push_back(make_tuple(U[i][j], D[i][j], L[i][j], R[i][j])); for (int i = 0; i < n; i ++) { vector < int > temp, res; for (int j = 0; j < m; j ++) temp.push_back(A[i][j]); res = Gen(temp, 0); for (int j = 0; j < m; j ++) L[i][j] = res[j]; reverse(temp.begin(), temp.end()); res = Gen(temp, 0); for (int j = 0; j < m; j ++) R[i][j] = m - res[m - j - 1] - 1; } for (int j = 0; j < m; j ++) { vector < int > temp, res; for (int i = 0; i < n; i ++) temp.push_back(A[i][j]); res = Gen(temp, 0); for (int i = 0; i < n; i ++) U[i][j] = res[i]; reverse(temp.begin(), temp.end()); res = Gen(temp, 0); for (int i = 0; i < n; i ++) D[i][j] = n - res[n - i - 1] - 1; } for (int i = 0; i < n; i ++) for (int j = 0; j < m; j ++) { L[i][j] = j - L[i][j]; R[i][j] = R[i][j] - j; U[i][j] = i - U[i][j]; D[i][j] = D[i][j] - i; } sort(Cands.begin(), Cands.end()); Cands.resize(unique(Cands.begin(), Cands.end()) - Cands.begin()); for (int i = 0; i < (int)Cands.size(); i ++) { int a, b, c, d; tie(a, b, c, d) = Cands[i]; assert(a + 1 < b && c + 1 < d); qL[d].push_back(i); qR[c].push_back(i); qU[b].push_back(i); qD[a].push_back(i); } auto GetMin = [&](int l, int r) { int lg = Log[r - l]; return min(RMQ[lg][l], RMQ[lg][r - (1 << lg)]); }; for (int i = 2; i < N; i ++) Log[i] = Log[i >> 1] + 1; for (int i = 0; i < n; i ++) { for (int j = 0; j < m; j ++) RMQ[0][j] = U[i][j]; for (int lg = 1; lg < LG; lg ++) for (int j = 0; j + (1 << lg) <= m; j ++) RMQ[lg][j] = min(RMQ[lg - 1][j], RMQ[lg - 1][j + (1 << (lg - 1))]); for (int id : qU[i]) { int a, b, c, d; tie(a, b, c, d) = Cands[id]; if (GetMin(c + 1, d) < b - a) Cant[id] = 1; } for (int j = 0; j < m; j ++) RMQ[0][j] = D[i][j]; for (int lg = 1; lg < LG; lg ++) for (int j = 0; j + (1 << lg) <= m; j ++) RMQ[lg][j] = min(RMQ[lg - 1][j], RMQ[lg - 1][j + (1 << (lg - 1))]); for (int id : qD[i]) { int a, b, c, d; tie(a, b, c, d) = Cands[id]; if (GetMin(c + 1, d) < b - a) Cant[id] = 1; } } for (int j = 0; j < m; j ++) { for (int i = 0; i < n; i ++) RMQ[0][i] = L[i][j]; for (int lg = 1; lg < LG; lg ++) for (int i = 0; i + (1 << lg) <= n; i ++) RMQ[lg][i] = min(RMQ[lg - 1][i], RMQ[lg - 1][i + (1 << (lg - 1))]); for (int id : qL[j]) { int a, b, c, d; tie(a, b, c, d) = Cands[id]; if (GetMin(a + 1, b) < d - c) Cant[id] = 1; } for (int i = 0; i < n; i ++) RMQ[0][i] = R[i][j]; for (int lg = 1; lg < LG; lg ++) for (int i = 0; i + (1 << lg) <= n; i ++) RMQ[lg][i] = min(RMQ[lg - 1][i], RMQ[lg - 1][i + (1 << (lg - 1))]); for (int id : qR[j]) { int a, b, c, d; tie(a, b, c, d) = Cands[id]; if (GetMin(a + 1, b) < d - c) Cant[id] = 1; } } int Cnt = 0; for (int i = 0; i < (int)Cands.size(); i ++) if (!Cant[i]) Cnt ++; return Cnt; }
#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...