#include <bits/stdc++.h>
using namespace std;
int main(int argc, char* argv[]) {
bool debug = (argc >= 2 && std::string(argv[1]) == "--debug");
int n, m, k;
cin >> n >> m >> k;
vector<vector<long long>> a(n, vector<long long>(m));
vector<vector<long long>> pref(n, vector<long long>(m + 1));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> a[i][j];
pref[i][j + 1] = pref[i][j] + a[i][j];
}
}
if (debug) {
cerr << "pref:\n";
for (int i = 0; i < n; i++) {
for (int j = 0; j <= m; j++) {
cerr << pref[i][j] << (j < m ? ' ' : '\n');
}
}
}
// Całe wiersze będące ciągami nierosnącymi (a[j] >= a[j+1]) -> jedna kolekcja (potem sort malejaco)
vector<long long> sortedAll;
vector<vector<long long>> wierszeStare;
for (int i = 0; i < n; i++) {
bool nierosnacy = true;
for (int j = 0; j < m - 1; j++) {
if (a[i][j] < a[i][j + 1]) {
nierosnacy = false;
break;
}
}
if (nierosnacy) {
for (int j = 0; j < m; j++) {
sortedAll.push_back(a[i][j]);
}
} else {
wierszeStare.push_back(a[i]);
}
}
sort(sortedAll.begin(), sortedAll.end(), greater<long long>());
// Zbiory po m elementów (kolejne fragmenty tablicy posortowanej malejaco)
vector<vector<long long>> chunks;
for (size_t i = 0; i < sortedAll.size(); i += static_cast<size_t>(m)) {
vector<long long> chunk;
for (size_t j = i; j < sortedAll.size() && j < i + static_cast<size_t>(m); j++) {
chunk.push_back(sortedAll[j]);
}
chunks.push_back(std::move(chunk));
}
// Jedna kolekcja list: najpierw zbiory z wierszy nierosnących, potem pozostałe wiersze
vector<vector<long long>> jednaKolekcja;
jednaKolekcja.reserve(chunks.size() + wierszeStare.size());
jednaKolekcja.insert(jednaKolekcja.end(), chunks.begin(), chunks.end());
jednaKolekcja.insert(jednaKolekcja.end(), wierszeStare.begin(), wierszeStare.end());
// Narastająca suma w każdej liście: 1 2 100 400 -> 1 3 103 503
for (auto& row : jednaKolekcja) {
for (size_t i = 1; i < row.size(); i++) {
row[i] += row[i - 1];
}
}
// Sortowanie malejąco po najwyższej sumie (ostatni element = suma całego wiersza)
sort(jednaKolekcja.begin(), jednaKolekcja.end(),
[](const vector<long long>& a, const vector<long long>& b) {
return a.back() > b.back();
});
if (debug) {
cerr << "wiersze nierosnace -> lacznie " << sortedAll.size() << " el. malejaco: ";
for (size_t i = 0; i < sortedAll.size(); i++) {
cerr << sortedAll[i] << (i + 1 < sortedAll.size() ? ' ' : '\n');
}
cerr << "jedna kolekcja — narastająca suma, posortowana malejąco po sumie końcowej ("
<< jednaKolekcja.size() << " list):\n";
for (size_t i = 0; i < jednaKolekcja.size(); i++) {
cerr << " [" << i << "]: ";
for (size_t t = 0; t < jednaKolekcja[i].size(); t++) {
cerr << jednaKolekcja[i][t] << (t + 1 < jednaKolekcja[i].size() ? ' ' : '\n');
}
}
}
long long result = 0;
int toEat = k;
int it =0;
while(toEat >= m*2) {
result += jednaKolekcja[it][m-1];
toEat -= m;
it++;
}
struct BestTwo {
long long wartosc;
int kolumna; // indeks listy w `jednaKolekcja`
};
vector<BestTwo> bestK(m + 1, BestTwo{0, -1});
vector<BestTwo> secondK(m + 1, BestTwo{0, -1});
for (int r = it; r < (int)jednaKolekcja.size(); r++) {
// take == 0 ma wartość 0 (nie wybieramy nic z listy), więc nie aktualizujemy tutaj.
for (int take = 1; take <= m; take++) {
long long cand = jednaKolekcja[r][take - 1]; // prefix sum po `take`
if (cand > bestK[take].wartosc) {
secondK[take] = bestK[take];
bestK[take] = BestTwo{cand, r};
} else if (cand > secondK[take].wartosc) {
secondK[take] = BestTwo{cand, r};
}
}
}
long long ans = 0;
if (toEat == 0) {
ans = 0;
} else if (toEat <= m) {
ans = bestK[toEat].wartosc;
} else {
for (int x = 1; x <= m; x++) {
int y = toEat - x;
if (y < 1 || y > m) continue;
BestTwo bx = bestK[x];
BestTwo by = bestK[y];
if (bx.kolumna != by.kolumna) {
ans = max(ans, bx.wartosc + by.wartosc);
} else {
ans = max(ans, bx.wartosc + secondK[y].wartosc);
ans = max(ans, secondK[x].wartosc + by.wartosc);
}
}
}
result += ans;
cout << result << "\n";
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | #include <bits/stdc++.h> using namespace std; int main(int argc, char* argv[]) { bool debug = (argc >= 2 && std::string(argv[1]) == "--debug"); int n, m, k; cin >> n >> m >> k; vector<vector<long long>> a(n, vector<long long>(m)); vector<vector<long long>> pref(n, vector<long long>(m + 1)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> a[i][j]; pref[i][j + 1] = pref[i][j] + a[i][j]; } } if (debug) { cerr << "pref:\n"; for (int i = 0; i < n; i++) { for (int j = 0; j <= m; j++) { cerr << pref[i][j] << (j < m ? ' ' : '\n'); } } } // Całe wiersze będące ciągami nierosnącymi (a[j] >= a[j+1]) -> jedna kolekcja (potem sort malejaco) vector<long long> sortedAll; vector<vector<long long>> wierszeStare; for (int i = 0; i < n; i++) { bool nierosnacy = true; for (int j = 0; j < m - 1; j++) { if (a[i][j] < a[i][j + 1]) { nierosnacy = false; break; } } if (nierosnacy) { for (int j = 0; j < m; j++) { sortedAll.push_back(a[i][j]); } } else { wierszeStare.push_back(a[i]); } } sort(sortedAll.begin(), sortedAll.end(), greater<long long>()); // Zbiory po m elementów (kolejne fragmenty tablicy posortowanej malejaco) vector<vector<long long>> chunks; for (size_t i = 0; i < sortedAll.size(); i += static_cast<size_t>(m)) { vector<long long> chunk; for (size_t j = i; j < sortedAll.size() && j < i + static_cast<size_t>(m); j++) { chunk.push_back(sortedAll[j]); } chunks.push_back(std::move(chunk)); } // Jedna kolekcja list: najpierw zbiory z wierszy nierosnących, potem pozostałe wiersze vector<vector<long long>> jednaKolekcja; jednaKolekcja.reserve(chunks.size() + wierszeStare.size()); jednaKolekcja.insert(jednaKolekcja.end(), chunks.begin(), chunks.end()); jednaKolekcja.insert(jednaKolekcja.end(), wierszeStare.begin(), wierszeStare.end()); // Narastająca suma w każdej liście: 1 2 100 400 -> 1 3 103 503 for (auto& row : jednaKolekcja) { for (size_t i = 1; i < row.size(); i++) { row[i] += row[i - 1]; } } // Sortowanie malejąco po najwyższej sumie (ostatni element = suma całego wiersza) sort(jednaKolekcja.begin(), jednaKolekcja.end(), [](const vector<long long>& a, const vector<long long>& b) { return a.back() > b.back(); }); if (debug) { cerr << "wiersze nierosnace -> lacznie " << sortedAll.size() << " el. malejaco: "; for (size_t i = 0; i < sortedAll.size(); i++) { cerr << sortedAll[i] << (i + 1 < sortedAll.size() ? ' ' : '\n'); } cerr << "jedna kolekcja — narastająca suma, posortowana malejąco po sumie końcowej (" << jednaKolekcja.size() << " list):\n"; for (size_t i = 0; i < jednaKolekcja.size(); i++) { cerr << " [" << i << "]: "; for (size_t t = 0; t < jednaKolekcja[i].size(); t++) { cerr << jednaKolekcja[i][t] << (t + 1 < jednaKolekcja[i].size() ? ' ' : '\n'); } } } long long result = 0; int toEat = k; int it =0; while(toEat >= m*2) { result += jednaKolekcja[it][m-1]; toEat -= m; it++; } struct BestTwo { long long wartosc; int kolumna; // indeks listy w `jednaKolekcja` }; vector<BestTwo> bestK(m + 1, BestTwo{0, -1}); vector<BestTwo> secondK(m + 1, BestTwo{0, -1}); for (int r = it; r < (int)jednaKolekcja.size(); r++) { // take == 0 ma wartość 0 (nie wybieramy nic z listy), więc nie aktualizujemy tutaj. for (int take = 1; take <= m; take++) { long long cand = jednaKolekcja[r][take - 1]; // prefix sum po `take` if (cand > bestK[take].wartosc) { secondK[take] = bestK[take]; bestK[take] = BestTwo{cand, r}; } else if (cand > secondK[take].wartosc) { secondK[take] = BestTwo{cand, r}; } } } long long ans = 0; if (toEat == 0) { ans = 0; } else if (toEat <= m) { ans = bestK[toEat].wartosc; } else { for (int x = 1; x <= m; x++) { int y = toEat - x; if (y < 1 || y > m) continue; BestTwo bx = bestK[x]; BestTwo by = bestK[y]; if (bx.kolumna != by.kolumna) { ans = max(ans, bx.wartosc + by.wartosc); } else { ans = max(ans, bx.wartosc + secondK[y].wartosc); ans = max(ans, secondK[x].wartosc + by.wartosc); } } } result += ans; cout << result << "\n"; return 0; } |
English