Submission #669876

#TimeUsernameProblemLanguageResultExecution timeMemory
669876borisAngelovNafta (COI15_nafta)C++11
100 / 100
437 ms120672 KiB
#include <iostream> #include <utility> #include <queue> #include <tuple> using namespace std; const int maxn = 3005; int n, m; char table[maxn][maxn]; pair<int, int> dirs[4] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; int component_idx = 0; int component[maxn][maxn]; int sum[maxn * maxn]; int left_end[maxn * maxn]; int right_end[maxn * maxn]; bool seen[maxn * maxn]; int dp[maxn][maxn]; int cost[maxn][maxn]; int interval[maxn]; void dfs(int x, int y) { component[x][y] = component_idx; for (int d = 0; d < 4; ++d) { int new_x = x + dirs[d].first; int new_y = y + dirs[d].second; if (new_x < 1 || new_x > n || new_y < 1 || new_y > m) continue; if (table[new_x][new_y] == '.' || component[new_x][new_y] != 0) continue; dfs(new_x, new_y); } } void divideAndConquer(int row, int l, int r, int optl, int optr) { if (l > r) return; int mid = (l + r) >> 1; int opt = -1; int bestValue = -1000000; for (int i = optl; i <= min(mid, optr); ++i) { if (dp[row - 1][i] + cost[i][mid] > bestValue) { bestValue = dp[row - 1][i] + cost[i][mid]; opt = i; } } dp[row][mid] = bestValue; divideAndConquer(row, l, mid - 1, optl, opt); divideAndConquer(row, mid + 1, r, opt, optr); } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> m; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { cin >> table[i][j]; } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if (component[i][j] == 0 && table[i][j] != '.') { component_idx++; dfs(i, j); } } } for (int i = 1; i <= component_idx; ++i) { left_end[i] = m + 1; right_end[i] = 0; } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if (component[i][j] != 0) { sum[component[i][j]] += (table[i][j] - '0'); left_end[component[i][j]] = min(left_end[component[i][j]], j); right_end[component[i][j]] = max(right_end[component[i][j]], j); } } } for (int j = 1; j <= m; ++j) { int current = 0; for (int i = 1; i <= n; ++i) { if (seen[component[i][j]] == false) { seen[component[i][j]] = true; interval[right_end[component[i][j]]] += sum[component[i][j]]; current += sum[component[i][j]]; } } for (int i = 1; i <= n; ++i) { seen[component[i][j]] = false; } for (int j1 = 0; j1 < j; ++j1) { cost[j1][j] += current; } int to_left = current - interval[j]; for (int j1 = j + 1; j1 <= m; ++j1) { cost[j][j1] -= to_left; to_left -= interval[j1]; } for (int i = 1; i <= m; ++i) { interval[i] = 0; } } for (int i = 1; i <= m; ++i) { divideAndConquer(i, 1, n, 0, n); for (int j = 1; j <= n; ++j) { dp[i][j] = max(dp[i][j], dp[i][j - 1]); } } for (int i = 1; i <= m; ++i) { cout << dp[i][n] << "\n"; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...