This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int MAXN = 1e5;
const int MAXM = 50;
int cur_r = 0;
ll ans = 0;
class edge {
public:
int x, y, w;
edge(int x, int y, int w) : x(x), y(y), w(w){}
};
int uf[MAXN*MAXM];
int rnk[MAXN*MAXM];
pii top[MAXN*MAXM];
int row_req[MAXN][MAXM]; // first row where it is no longer the top
bool active[MAXN+1][MAXM];
vector<edge> adj[2]; // mst
vector<pii> edges[MAXM];
int dist[MAXM/2][MAXM/2];
int to_comp[MAXN+1][MAXM];
int miniuf[MAXM];
int lft[MAXM+1];
int dpth[MAXM/2];
vector<int> up_adj[MAXM/2];
bool cur = 0;
int n, m;
int find(int i) {
return (uf[i] == -1) ? i : (uf[i] = find(uf[i]));
}
int mfind(int i) {
return (miniuf[i] == -1) ? i : (miniuf[i] = mfind(miniuf[i]));
}
bool operator<(edge &a, edge &b) {
return a.w < b.w;
}
void minimerge(int a, int b, int d) {
a = mfind(a);
b = mfind(b);
if (a == b) return;
if (lft[a] < lft[b]) dpth[lft[b]] = d;
else dpth[lft[a]] = d;
miniuf[a] = b;
lft[b] = min(lft[a], lft[b]);
}
void merge(int a, int b) {
a = find(a);
b = find(b);
if (a == b) return;
if (top[a] < top[b]) row_req[top[b].first][top[b].second] = cur_r;
else row_req[top[a].first][top[a].second] = cur_r;
if (rnk[a] < rnk[b]) swap(a, b);
uf[b] = a;
if (rnk[a] == rnk[b]) rnk[a]++;
top[a] = min(top[a], top[b]);
}
int hsh(int i, int j) {
return m*i+j;
}
void make_dists(int cur, int topval, int sz, int p = -1, int block = 0) {
if (cur != topval && cur < sz) {
dist[topval][cur] = block;
return;
}
for (pii e: edges[cur]) {
int nxt = e.first;
if (nxt == p) continue;
make_dists(nxt, topval, sz, cur, max(block, e.second));
}
}
void construct(int sz) {
vector<edge> mst2;
for (int i = 0; i < sz; i++) {
fill(dist[i], dist[i]+sz, n);
make_dists(i, i, sz);
for (int j = 0; j < i; j++) mst2.push_back(edge(i, j, dist[i][j]));
}
sort(mst2.begin(), mst2.end());
fill(miniuf, miniuf+sz, -1);
for (edge e: mst2) {
int a = mfind(e.x);
int b = mfind(e.y);
if (a != b) {
adj[cur].push_back(e);
miniuf[a] = b;
}
}
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(NULL);
cin >> n >> m;
for (int i = 0; i < n; i++) {
string s; cin >> s;
for (int j = 0; j < m; j++) {
active[i][j] = s[j]-'0';
top[hsh(i, j)] = pii(i, j);
row_req[i][j] = n;
}
}
fill(uf, uf+n*m, -1);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m-1; j++) {
if (active[i][j] && active[i][j+1]) merge(hsh(i, j), hsh(i, j+1));
}
cur_r++;
if (i < n-1) {
for (int j = 0; j < m; j++) {
if (active[i][j] && active[i+1][j]) merge(hsh(i, j), hsh(i+1, j));
}
}
}
for (int i = 1; i < n; i++) {
for (int j = 0; j < m; j++) {
if (active[i][j]) ans += (ll) i*(row_req[i][j]-i);
}
}
// cout << ans << "\n";
int prevcnt = 0;
for (int i = n-1; i >= 0; i--) {
vector<pii> ranges;
for (int j = 0; j < prevcnt; j++) {
up_adj[j].clear();
}
int pl = -2;
int pr = -2;
for (int j = 0; j < m; j++) {
if (!active[i][j]) continue;
if (j > pr+1) {
if (pl != -2) {
ranges.push_back(pii(pl, pr));
}
pl = j;
pr = j-1;
}
pr++;
if (active[i+1][j]) up_adj[to_comp[i+1][j]].push_back(ranges.size());
to_comp[i][j] = ranges.size();
}
if (pl != -2) {
ranges.push_back(pii(pl, pr));
}
if (ranges.size()) {
adj[cur].clear();
vector<edge> mst_edges;
for (int j = 0; j < ranges.size(); j++) {
miniuf[j] = -1;
lft[j] = j;
dpth[j] = n;
edges[j].clear();
}
for (int j = 0; j < prevcnt; j++) {
miniuf[j+ranges.size()] = -1;
lft[j+ranges.size()] = ranges.size();
for (int a: up_adj[j]) mst_edges.push_back(edge(a, j+ranges.size(), i+1));
edges[j+ranges.size()].clear();
}
for (edge e: adj[!cur]) mst_edges.push_back(edge(e.x+ranges.size(), e.y+ranges.size(), e.w));
for (edge e: mst_edges) {
int a = e.x;
int b = e.y;
if (mfind(a) != mfind(b)) {
minimerge(a, b, e.w);
edges[a].push_back(pii(b, e.w));
edges[b].push_back(pii(a, e.w));
}
} // we have a tree, and we want to simplify it
for (int j = 0; j < ranges.size()-1; j++) {
int k = j+1;
if (mfind(j) != mfind(k)) {
minimerge(j, k, n);
edges[j].push_back(pii(k, n));
edges[k].push_back(pii(j, n));
}
}
construct(ranges.size());
ll sub = 0;
for (int j = 0; j < ranges.size(); j++) {
sub += (dpth[j]-i);
}
// cout << sub << "\n";
ans += sub;
}
prevcnt = ranges.size();
cur = !cur;
}
cout << ans << "\n";
}
Compilation message (stderr)
raspad.cpp: In function 'int main()':
raspad.cpp:162:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
162 | for (int j = 0; j < ranges.size(); j++) {
| ~~^~~~~~~~~~~~~~~
raspad.cpp:184:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
184 | for (int j = 0; j < ranges.size()-1; j++) {
| ~~^~~~~~~~~~~~~~~~~
raspad.cpp:194:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
194 | for (int j = 0; j < ranges.size(); j++) {
| ~~^~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |