Submission #142594

#TimeUsernameProblemLanguageResultExecution timeMemory
142594DrumpfTheGodEmperorDango Maker (JOI18_dango_maker)C++14
13 / 100
69 ms71264 KiB
#include <bits/stdc++.h> #define bp __builtin_popcountll #define pb push_back #define in(s) freopen(s, "r", stdin); #define out(s) freopen(s, "w", stdout); #define inout(s, end1, end2) freopen((string(s) + "." + end1).c_str(), "r", stdin),\ freopen((string(s) + "." + end2).c_str(), "w", stdout); #define fi first #define se second #define bw(i, r, l) for (int i = r - 1; i >= l; i--) #define fw(i, l, r) for (int i = l; i < r; i++) #define fa(i, x) for (auto i: x) using namespace std; const int mod = 1e9 + 7, inf = 1061109567; const long long infll = 4557430888798830399; const int N = 3005, MXDSU = 6e6; int n, m, ans = 0, idHorizontal[N][N], idVertical[N][N], pos = 0, mnRow[N], mxRow[N], dp[N][8]; int mnCol[N], mxCol[N]; char a[N][N]; int p[MXDSU], sz[MXDSU], row[MXDSU], col[MXDSU]; //Maximally 6 million DSU bool dir[MXDSU]; vector<vector<int>> inDSU; bool check(int i, int j, string pattern) { if (i < 0 || i >= n || j + pattern.length() - 1 >= m || j < 0) return false; fw (k, 0, pattern.length()) { if (a[i][j + k] != pattern[k]) return false; } return true; } int getp(int u) { return u == p[u] ? u : p[u] = getp(p[u]); } void joint(int u, int v) { u = getp(u), v = getp(v); if (u == v) return; if (sz[u] < sz[v]) swap(u, v); sz[u] += sz[v]; p[v] = u; } int getRowLength(int row) { return mxCol[row] - mnCol[row] + 1; } int getColLength(int col) { return mxRow[col] - mnRow[col] + 1; } bool checkMasks(int curMask, int prvMask, int curMaskLen, int prvMaskLen, int diff) { //diff represents mnRow[prvColumn] - mnRow[curColumn] //All meeting rows must be the same status (picked or not picked) fw (i, diff, min(curMaskLen, prvMaskLen) + diff) { int curBit = ((curMask >> i) & 1), prvBit = ((prvMask >> (i - diff)) & 1); if (curBit != prvBit) return false; } return true; } int getExtraRows(int mask, int col, int diff) { int ans = 0; fw (i, 0, min(diff, 3)) if (mask & (1 << i)) { if (getRowLength(mnRow[col] + i) < 3) return -1; ans++; } return ans; } signed main() { #ifdef BLU in("blu.inp"); // out("out1.out"); #endif ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m; fw (i, 0, n) fw (j, 0, m) cin >> a[i][j]; memset(idHorizontal, -1, sizeof idHorizontal); memset(idVertical, -1, sizeof idVertical); // cout << sizeof(idHorizontal) + sizeof(idVertical) + sizeof(p) + sizeof(sz) + sizeof(row) + // sizeof(col) + sizeof(dir) + sizeof(inDSU) << "\n"; fw (i, 0, n) { fw (j, 0, m) { // cout << "i = " << i << " j = " << j << " pos = " << pos << "\n"; if (check(i, j, "RGW")) { idHorizontal[i][j] = pos; row[pos] = i, col[pos] = j; dir[pos] = 0; pos++; } if (check(i, j, "R") && check(i + 1, j, "G") && check(i + 2, j, "W")) { idVertical[i][j] = pos; row[pos] = i, col[pos] = j; dir[pos] = 1; pos++; } } } fw (i, 0, pos) p[i] = i, sz[i] = 1; fw (i, 0, n) fw (j, 0, m) { if (check(i, j, "RGW")) { if (check(i + 1, j, "G") && check(i + 2, j, "W")) joint(idHorizontal[i][j], idVertical[i][j]); if (check(i - 1, j + 1, "R") && check(i + 1, j + 1, "W")) joint(idHorizontal[i][j], idVertical[i - 1][j + 1]); if (check(i - 2, j + 2, "R") && check(i - 1, j + 2, "G")) joint(idHorizontal[i][j], idVertical[i - 2][j + 2]); } } //Use dp on each DSU and solve them separately. inDSU.resize(pos); fw (i, 0, pos) inDSU[getp(i)].pb(i); fw (i, 0, m) mnRow[i] = inf, mxRow[i] = -1; fw (i, 0, n) mnCol[i] = inf, mxCol[i] = -1; fw (i, 0, pos) if (getp(i) == i) { int mnColumn = inf, mxColumn = -1, minRow = inf, maxRow = -1; // cout << "DSU of " << i << "\n"; fa (j, inDSU[i]) { // cout << row[j] + 1 << " " << col[j] + 1 << " " << (dir[j] ? "Vertical" : "Horizontal") << "\n"; if (dir[j] == 0) { //Horizontal mnColumn = min(mnColumn, col[j]); mxColumn = max(mxColumn, col[j] + 2); minRow = min(minRow, row[j]); maxRow = max(maxRow, row[j]); mnRow[col[j]] = min(mnRow[col[j]], row[j]); mnRow[col[j] + 1] = min(mnRow[col[j] + 1], row[j]); mnRow[col[j] + 2] = min(mnRow[col[j] + 2], row[j]); mxRow[col[j]] = max(mxRow[col[j]], row[j]); mxRow[col[j] + 1] = max(mxRow[col[j] + 1], row[j]); mxRow[col[j] + 2] = max(mxRow[col[j] + 2], row[j]); mnCol[row[j]] = min(mnCol[row[j]], col[j]); mxCol[row[j]] = max(mxCol[row[j]], col[j] + 2); } else { //Vertical mnColumn = min(mnColumn, col[j]); mxColumn = max(mxColumn, col[j]); minRow = min(minRow, row[j]); maxRow = max(maxRow, row[j] + 2); mnRow[col[j]] = min(mnRow[col[j]], row[j]); mxRow[col[j]] = max(mxRow[col[j]], row[j] + 2); mnCol[row[j]] = min(mnCol[row[j]], col[j]); mnCol[row[j] + 1] = min(mnCol[row[j] + 1], col[j]); mnCol[row[j] + 2] = min(mnCol[row[j] + 2], col[j]); mxCol[row[j]] = max(mxCol[row[j]], row[j]); mxCol[row[j] + 1] = max(mxCol[row[j] + 1], col[j]); mxCol[row[j] + 2] = max(mxCol[row[j] + 2], col[j]); } } fw (j, mnColumn, mxColumn + 1) { // cout << "col " << j + 1 << " mnRow = " << mnRow[j] + 1 << " mxRow = " << mxRow[j] + 1 << "\n"; int colLen = getColLength(j); fw (mask, 0, (1 << colLen)) { //ith bit of mask represents a[mnRow[j] + i][j] dp[j][mask] = 0; if (j > mnColumn) { int prvColLen = getColLength(j - 1), diff = mnRow[j - 1] - mnRow[j]; int extraRows = getExtraRows(mask, j, diff); // if (mask == 5) cout << "ExtraRows = " << extraRows << "\n"; if (extraRows == -1) continue; //Invalid mask (Picking non - RGW rows) fw (prvMask, 0, (1 << prvColLen)) { // if (mask == 5 && prvMask == 1) { // cout << checkMasks(mask, prvMask, colLen, prvColLen, diff) << "\n"; // cout << "diff = " << diff << "\n"; // } if (checkMasks(mask, prvMask, colLen, prvColLen, diff)) { dp[j][mask] = max(dp[j][mask], dp[j - 1][prvMask] + extraRows); } } } else { int extraRows = getExtraRows(mask, j, inf); if (extraRows == -1) continue; dp[j][mask] = extraRows; } if (colLen == 3 && mask == 0) dp[j][mask]++; //Pick column } } // fw (j, mnColumn, mxColumn + 1) fw (mask, 0, 8) if (dp[j][mask]) { // cout << "Dp[" << j + 1 << "][" << mask << "] = " << dp[j][mask] << "\n"; // } int dsuAns = 0; fw (mask, 0, 8) dsuAns = max(dsuAns, dp[mxColumn][mask]); fw (j, mnColumn, mxColumn + 1) { mnRow[j] = inf; mxRow[j] = -1; } fw (j, minRow, maxRow + 1) { mnCol[j] = inf; mxCol[j] = -1; } ans += dsuAns; } cout << ans; return 0; }

Compilation message (stderr)

dango_maker.cpp: In function 'bool check(int, int, std::__cxx11::string)':
dango_maker.cpp:24:50: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  if (i < 0 || i >= n || j + pattern.length() - 1 >= m || j < 0) return false;
                         ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
dango_maker.cpp:11:39: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define fw(i, l, r) for (int i = l; i < r; i++)
dango_maker.cpp:25:6:
  fw (k, 0, pattern.length()) {
      ~~~~~~~~~~~~~~~~~~~~~~            
dango_maker.cpp:25:2: note: in expansion of macro 'fw'
  fw (k, 0, pattern.length()) {
  ^~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...