/**
* author : Lăng Trọng Đạt
* created: 02-08-2025
**/
#include <bits/stdc++.h>
using namespace std;
#ifndef LANG_DAT
#define db(...) ;
#endif // LANG_DAT
#define int long long
#define f first
#define se second
#define pb push_back
#define all(v) (v).begin(), (v).end()
#define FOR(i, a, b) for (int i = (a); (i) <= (b); (i++))
#define FD(i, lo, up) for (int i = (up); (i) >= (lo); i--)
#define si(x) (int)(x.size())
bool mx(int& a, int b) { if (b > a) {a = b; return true;} return false;}
bool mi(int& a, int b) { if (b < a) {a = b; return true;} return false;}
using pii = pair<int, int>;
using vi = vector<int>;
const int INF = 1e18 + 5;
const int MOD = 1e9 + 7;
const int N = 2e3 + 5;
int g[N][N];
int n, m, k, q, a, b, c;
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
int comp[N][N], sum[N * N], trai[N * N], comp_cnt = 0;
vector<pii> oil[N];
void pre() {
FOR(i, 1, n) FOR(j, 1, m) {
if (comp[i][j] == 0 && g[i][j] != -1) {
trai[++comp_cnt] = m + 1;
queue<pii> q;
q.push({i, j});
while (si(q)) {
auto[x, y] = q.front(); q.pop();
if (1 <= x && x <= n && 1 <= y && y <= m && g[x][y] != -1 && !comp[x][y]) {
comp[x][y] = comp_cnt;
sum[comp_cnt] += g[x][y];
mi(trai[comp_cnt], y);
FOR(k, 0, 3) {
q.push({x + dx[k], y + dy[k]});
}
}
}
}
}
FOR(i, 1, m) {
vector<vector<int>> cur;
FOR(x, 1, n) {
if (g[x][i] != -1) {
cur.push_back({trai[comp[x][i]], comp[x][i], sum[comp[x][i]]});
}
}
sort(all(cur));
cur.resize(unique(all(cur)) - cur.begin());
int add = 0;
for(auto v : cur) {
oil[i].push_back({v[0], v[2]});
}
for (int j = si(oil[i]) - 2; j >= 0; j--) {
oil[i][j].se += oil[i][j + 1].se;
}
}
}
int dp[N][N]; // dp[i][j]: nếu khoan j cái và cái cuối cùng ở vị trí <= i thì tối đa là ?
int opt[N]; // opt[l] <= opt[mid] <= opt[r]
void solve(int l, int r, int khoan) {
if (r - l > 1) {
int mid = (l + r) / 2, add = 0;
auto id = prev(upper_bound(all(oil[mid]), make_pair(opt[r], INF))) - oil[mid].begin();
// db(l, r, mid, oil[mid][id], opt[l], opt[r])
for (int i = id; i >= 0 && oil[mid][i].first >= opt[l]; i--) {
if (mx(dp[khoan][mid], dp[khoan - 1][oil[mid][i].f - 1] + oil[mid][i].se)) {
opt[mid] = oil[mid][i].f;
}
// if (mid == 5 && khoan == 2) {
// db(mid, dp[khoan - 1][oil[mid][i].f - 1], oil[mid][i]);
// }
}
solve(l, mid, khoan);
solve(mid, r, khoan);
}
}
void trau() {
FOR(j, 1, m) {
FOR(i, 1, m) {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
vector<vector<int>> oil;
FOR(x, 1, n) {
if (g[x][i] != -1) {
oil.push_back({trai[comp[x][i]], comp[x][i], sum[comp[x][i]]});
}
}
sort(all(oil));
oil.resize(unique(all(oil)) - oil.begin());
reverse(all(oil));
int add = 0;
// for (auto[left_most, id, tong] : oil) {
for (auto& cur : oil) {
add += cur[2];
mx(dp[i][j], dp[cur[0] - 1][j - 1] + add);
}
db(i, j, dp[i][j])
}
cout << dp[m][j] << "\n";
}
}
int32_t main() {
cin.tie(0)->sync_with_stdio(0);
if (fopen("hi.inp", "r")) {
freopen("hi.inp", "r", stdin);
// freopen("hi.out", "w", stdout);
}
cin >> n >> m;
FOR(i, 1, n) FOR(j, 1, m) {
char c; cin >> c;
g[i][j] = (c == '.' ? -1 : c - '0');
}
memset(dp, -1, sizeof(dp));
FOR(i, 0, m) dp[0][i] = 0;
pre();
opt[0] = 0, opt[m + 1] = m + 1;
FOR(i, 1, m) {
dp[i - 1][0] = 0;
FOR(j, 1, m) opt[j] = m + 1;
// db(i, oil[i])
solve(0, m + 1, i);
FOR(j, 1, m) {
mx(dp[i][j], dp[i][j - 1]);
// db(i, j, dp[i][j])
}
cout << dp[i][m] << "\n";
}
}
컴파일 시 표준 에러 (stderr) 메시지
nafta.cpp: In function 'int32_t main()':
nafta.cpp:122:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
122 | freopen("hi.inp", "r", stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |