#include<bits/stdc++.h>
using namespace std;
#define MP make_pair
#define pii pair<int,int>
#define ppiii pair<pii,int>
#define FF first.first
#define FS first.second
#define MAXN 2010
struct DSU{
vector<int> sizes, parents;
DSU(int n){
sizes = parents = vector<int>(n);
for(int i = 0; i < n; ++i){
sizes[i] = 1;
parents[i] = i;
}
}
int find(int current){
int newRoot = current; // variavel para guardar nova raiz
while(newRoot != parents[newRoot]) // enquanto nao encontro no raiz
newRoot = parents[newRoot]; // subo na arvore
// compressao de caminho (*) REMOVER SE FOR ROLLBACK
int next; // backup do pai
while(parents[current] != newRoot){ // enquanto nao acho a nova raiz
next = parents[current]; // faco o backup do pai
parents[current] = newRoot; // digo que o pai eh a raiz achada (*)
}
return newRoot; // retornamo a raiz da arvore
}
void onion(int a, int b){
a = find(a); b = find(b); // unimos uma raiz a outra
if(a == b) return; // se for a mesma raiz, nao tenho o que unir
if(sizes[a] < sizes[b]) swap(a,b); // quero unir "b" a "a"
sizes[a] += sizes[b]; // atualizando tamanho de "a"
parents[b] = a; // pai de "b" eh "a"
}
};
int c[MAXN][MAXN];
int pd[MAXN][MAXN];
int getc(int i, int j, int k){
if(i > j) return -2;
int myc = c[j][j];
int interc = c[k][j];
return pd[i - 1][k] + myc - interc;
}
void solve(int i, int l, int r, int searchL, int searchR){
if(l > r) return;
int j = (l + r) / 2;
if(pd[i][j] == -1){
int validR = min(j, searchR);
if(searchL > validR){
pd[i][j] = -2;
}else{
auto best = MP(getc(i, j, validR), validR);
for(int k = searchL; k < validR; ++k){
best = max(best, MP(getc(i, j, k), k));
}
pd[i][j] = best.first;
solve(i, l, j - 1, searchL, best.second);
solve(i, j + 1, r, best.second, searchR);
}
}
}
int main(){
iostream::sync_with_stdio(false);
memset(pd, -1, sizeof pd);
int n, m; cin >> n >> m;
DSU dsu(n * m + 1);
vector<vector<int>> g(n, vector<int>(m, -1));
vector<int> l(n * m, m + 1);
vector<int> r(n * m, 0);
vector<int> p(n * m, 0);
for(int i = 0; i < n; ++i){
string s; cin >> s;
for(int j = 0; j < m; ++j){
int x = i * m + j;
if(s[j] == '.') continue;
g[i][j] = s[j] - '0';
if(i > 0 && g[i - 1][j] >= 0) dsu.onion(x, x - m);
if(j > 0 && g[i][j - 1] >= 0) dsu.onion(x, x - 1);
}
}
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j){
int x = i * m + j;
int rangeId = dsu.find(x);
l[rangeId] = min(l[rangeId], j);
r[rangeId] = max(r[rangeId], j);
p[rangeId] += g[i][j];
}
}
for(int j = 0; j < m; ++j){
unordered_set<int> vis;
for(int i = 0; i < n; ++i){
if(g[i][j] == -1) continue;
int x = i * m + j;
int rangeId = dsu.find(x);
if(vis.count(rangeId)) continue;
vis.insert(rangeId);
c[j][j] += p[rangeId];
}
}
unordered_set<int> vis;
vector<pii> startsAt[m];
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j){
int x = dsu.find(i * m + j);
if(vis.count(x) == 0){
startsAt[l[x]].push_back({r[x], p[x]});
vis.insert(x);
}
}
}
for(int i = 0; i < m; ++i){
// c[j][j]: intersec entre i e j
for(int j = 0; j < i; ++j){
for(auto x : startsAt[j]){
if(x.first >= i) c[j][i] += x.second;
}
if(j) c[j][i] += c[j - 1][i];
}
}
// for(int i = 0; i < m; ++i){
// for(int j = 0; j < m; ++j){
// cout << c[i][j] << " ";
// }cout << endl;
// }
for(int i = 0; i < m; ++i){
pd[0][i] = c[i][i];
// cout << pd[0][i] << endl;
}
for(int i = 1; i < m; ++i){
solve(i, 0, m - 1, 0, m - 1);
}
for(int i = 0; i < m; ++i){
int ans = 0;
for(int j = 0; j < m; ++j){
// cout << pd[i][j] << " ";
ans = max(ans, pd[i][j]);
}
// cout << endl;
cout << ans << "\n";
}
}
Compilation message
nafta.cpp: In member function 'int DSU::find(int)':
nafta.cpp:26:9: warning: variable 'next' set but not used [-Wunused-but-set-variable]
26 | int next; // backup do pai
| ^~~~
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
9 ms |
16460 KB |
Output is correct |
2 |
Correct |
10 ms |
16460 KB |
Output is correct |
3 |
Correct |
8 ms |
16332 KB |
Output is correct |
4 |
Correct |
9 ms |
16460 KB |
Output is correct |
5 |
Correct |
10 ms |
16468 KB |
Output is correct |
6 |
Correct |
9 ms |
16460 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
9 ms |
16460 KB |
Output is correct |
2 |
Correct |
10 ms |
16460 KB |
Output is correct |
3 |
Correct |
8 ms |
16332 KB |
Output is correct |
4 |
Correct |
9 ms |
16460 KB |
Output is correct |
5 |
Correct |
10 ms |
16468 KB |
Output is correct |
6 |
Correct |
9 ms |
16460 KB |
Output is correct |
7 |
Correct |
42 ms |
23388 KB |
Output is correct |
8 |
Correct |
37 ms |
22492 KB |
Output is correct |
9 |
Correct |
28 ms |
21120 KB |
Output is correct |
10 |
Correct |
42 ms |
23320 KB |
Output is correct |
11 |
Correct |
36 ms |
23044 KB |
Output is correct |
12 |
Correct |
37 ms |
23176 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
9 ms |
16460 KB |
Output is correct |
2 |
Correct |
10 ms |
16460 KB |
Output is correct |
3 |
Correct |
8 ms |
16332 KB |
Output is correct |
4 |
Correct |
9 ms |
16460 KB |
Output is correct |
5 |
Correct |
10 ms |
16468 KB |
Output is correct |
6 |
Correct |
9 ms |
16460 KB |
Output is correct |
7 |
Correct |
42 ms |
23388 KB |
Output is correct |
8 |
Correct |
37 ms |
22492 KB |
Output is correct |
9 |
Correct |
28 ms |
21120 KB |
Output is correct |
10 |
Correct |
42 ms |
23320 KB |
Output is correct |
11 |
Correct |
36 ms |
23044 KB |
Output is correct |
12 |
Correct |
37 ms |
23176 KB |
Output is correct |
13 |
Execution timed out |
1114 ms |
311600 KB |
Time limit exceeded |
14 |
Halted |
0 ms |
0 KB |
- |