Submission #142554

# Submission time Handle Problem Language Result Execution time Memory
142554 2019-08-09T14:34:50 Z DrumpfTheGodEmperor Dango Maker (JOI18_dango_maker) C++14
0 / 100
221 ms 262148 KB
#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;
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[N * N], sz[N * N], row[N * N], col[N * N]; //Maximally 6 million DSU
bool dir[N * N];
vector<int> inDSU[N * N];
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 & (1 << i)), prvBit = (prvMask & (1 << (i - diff)));
		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);
	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.
	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]);
			}
		}
//		cout << "mnCol = " << mnColumn << " mxCol = " << mxColumn << "\n";
//		fw (j, minRow, maxRow + 1) {
//			cout << "row " << j + 1 << " mnCol = " << mnCol[j] + 1 << " mxCol = " << mxCol[j] + 1 << "\n"; 
//		}
		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 (extraRows == -1) continue; //Invalid mask (Picking non - RGW rows)
					fw (prvMask, 0, (1 << prvColLen)) {
						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

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 time Memory Grader output
1 Runtime error 221 ms 262148 KB Execution killed with signal 9 (could be triggered by violating memory limits)
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 221 ms 262148 KB Execution killed with signal 9 (could be triggered by violating memory limits)
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 221 ms 262148 KB Execution killed with signal 9 (could be triggered by violating memory limits)
2 Halted 0 ms 0 KB -