Submission #652913

#TimeUsernameProblemLanguageResultExecution timeMemory
652913GusterGoose27Nafta (COI15_nafta)C++11
100 / 100
606 ms111972 KiB
#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> pii;

const int MAXN = 2000;

int val[MAXN][MAXN];
int uf[MAXN*MAXN];
int sum[MAXN*MAXN];
pii uf_range[MAXN*MAXN];
int n, m;
map<pii, int> ranges;
int bit[MAXN];
int single_val[MAXN][MAXN]; // placing at i, drills j and above
int dp[MAXN+1][MAXN+1]; // pos i and above, j drills

class stree {
public:
	int sum = 0;
	int lp, rp;
	stree *l = nullptr;
	stree *r = nullptr;
	stree(int lv, int rv) {
		lp = lv;
		rp = rv;
		if (lp < rp) {
			int mid = (lp+rp)/2;
			l = new stree(lp, mid);
			r = new stree(mid+1, rp);
		}
	}
	void upd(int lv, int rv, int v) {
		if (lp > rv || rp < lv) return;
		if (lp >= lv && rp <= rv) {
			sum += v;
			return;
		}
		l->upd(lv, rv, v);
		r->upd(lv, rv, v);
	}
	int get(int p) {
		if (lp > p || rp < p) return 0;
		if (lp == rp) return sum;
		return sum+l->get(p)+r->get(p);
	}
};

int hsh(int i, int j) {
	return i*m+j;
}

int find(int i) {
	return (uf[i] == -1) ? i : (uf[i] = find(uf[i]));
}

void merge(int a, int b) {
	a = find(a);
	b = find(b);
	if (a != b) {
		uf[a] = b;
		sum[b] += sum[a];
		uf_range[b] = pii(min(uf_range[b].first, uf_range[a].first), max(uf_range[b].second, uf_range[a].second));
	}
}

void make_dp(int pos, int lp, int rp, int nlp, int nrp) {
	if (rp < lp) return;
	int cur = (lp+rp)/2;
	int best = nlp;
	int bestval = -1;
	for (int i = nlp; i <= nrp; i++) {
		int cval = single_val[i][pos]+dp[i+1][cur-1];
		if (cval > bestval) {
			bestval = cval;
			best = i;
		}
	}
	dp[pos][cur] = bestval;
	make_dp(pos, lp, cur-1, best, nrp);
	make_dp(pos, cur+1, rp, nlp, best);
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	cin >> n >> m;
	string s;
	for (int i = 0; i < n; i++) {
		cin >> s;
		for (int j = 0; j < m; j++) {
			int cur = hsh(i, j);
			if (s[j] == '.') val[i][j] = -1;
			else val[i][j] = s[j]-'0';
			sum[cur] = val[i][j];
			uf_range[cur] = pii(j, j);
			uf[cur] = -1;
		}
	}
	for (int i = 0; i < n-1; i++) {
		for (int j = 0; j < m; j++) {
			if (val[i][j] >= 0 && val[i+1][j] >= 0) merge(hsh(i, j), hsh(i+1, j));
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m-1; j++) {
			if (val[i][j] >= 0 && val[i][j+1] >= 0) merge(hsh(i, j), hsh(i, j+1));
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			int cur = hsh(i, j);
			if (val[i][j] >= 0 && uf[cur] == -1) ranges[uf_range[cur]] += sum[cur];
		}
	}
	stree *tree = new stree(0, m-1);
	auto r_pos = ranges.rbegin();
	for (int j = m-1; j >= 0; j--) {
		while (r_pos != ranges.rend() && r_pos->first.first >= j) {
			tree->upd(r_pos->first.first, r_pos->first.second, r_pos->second);
			r_pos++;
		}
		for (int i = j; i < m; i++) single_val[i][j] = tree->get(i);
	}
	for (int j = m-1; j >= 0; j--) make_dp(j, 1, m-j, j, m-1);
	for (int i = 1; i <= m; i++) cout << dp[0][i] << "\n";
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...