#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>
#include <set>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, k;
cin >> n >> m >> k;
vector<vector<long long>> stacks;
stacks.reserve(n);
vector<long long> decreasing;
decreasing.reserve(n * m);
for (int i = 0; i < n; ++i) {
bool increasing = false;
vector<long long> stack;
stack.resize(m);
for (int j = 0; j < m; ++j) {
cin >> stack[j];
increasing |= j > 0 && stack[j] > stack[j - 1];
}
if (increasing) {
for (int j = 1; j < m; ++j) {
stack[j] += stack[j - 1];
}
stacks.push_back(std::move(stack));
} else {
decreasing.insert(decreasing.end(), stack.begin(), stack.end());
}
}
ranges::sort(stacks, [](const auto &a, const auto &b) {
return a.back() > b.back();
});
ranges::sort(decreasing, ranges::greater{});
for (int j = 1; j < ssize(decreasing); ++j) {
decreasing[j] += decreasing[j - 1];
}
if (ssize(stacks) == 0) {
cout << decreasing[k - 1] << "\n";
return 0;
}
long long res{};
{ // rem = 0
int decreasingNum = k;
long long stacksSum = 0;
for (int i = 0;; ++i) {
if (decreasingNum < 0) {
break;
}
if (decreasingNum <= ssize(decreasing)) {
auto decRes = decreasingNum == 0 ? 0 : decreasing[decreasingNum - 1];
long long tmpRes = decRes + stacksSum;
if (tmpRes > res) {
res = tmpRes;
}
}
if (i == ssize(stacks)) {
break;
}
decreasingNum -= m;
stacksSum += stacks[i].back();
}
}
for (int rem = 1; rem < m; ++rem) {
auto cmp = [&](const auto &a, const auto &b) {
bool eq = stacks[a][rem - 1] == stacks[b][rem - 1];
if (eq) {
return a > b;
};
return stacks[a][rem - 1] > stacks[b][rem - 1];
};
set<long long, decltype(cmp)> prefixes(cmp);
for (int i = 0; i < ssize(stacks); ++i) {
prefixes.insert(i);
}
int prefix = *prefixes.begin();
int decreasingNum = k - rem;
long long stacksSum = stacks[prefix][rem - 1];
for (int i = 0; i < ssize(stacks); ++i) {
if (decreasingNum < 0) {
break;
}
if (decreasingNum <= ssize(decreasing)) {
auto decRes = decreasingNum == 0 ? 0 : decreasing[decreasingNum - 1];
auto tmpRes = decRes + stacksSum;
if (tmpRes > res) {
res = tmpRes;
}
}
decreasingNum -= m;
if (i == ssize(stacks) - 1) {
break;
}
if (prefix > i) {
stacksSum += stacks[i].back();
} else {
auto c1 = stacksSum + stacks[i + 1].back();
auto newPrefix = *next(prefixes.begin());
// czy usunąć prefix
auto c2 = stacksSum - stacks[prefix][rem - 1] + stacks[newPrefix][rem - 1] + stacks[i].back();
if (c2 > c1) {
prefix = newPrefix;
}
stacksSum = max(c1, c2);
}
prefixes.erase(i);
}
}
cout << res << "\n";
}
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 | #include <algorithm> #include <iostream> #include <ranges> #include <vector> #include <set> using namespace std; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, m, k; cin >> n >> m >> k; vector<vector<long long>> stacks; stacks.reserve(n); vector<long long> decreasing; decreasing.reserve(n * m); for (int i = 0; i < n; ++i) { bool increasing = false; vector<long long> stack; stack.resize(m); for (int j = 0; j < m; ++j) { cin >> stack[j]; increasing |= j > 0 && stack[j] > stack[j - 1]; } if (increasing) { for (int j = 1; j < m; ++j) { stack[j] += stack[j - 1]; } stacks.push_back(std::move(stack)); } else { decreasing.insert(decreasing.end(), stack.begin(), stack.end()); } } ranges::sort(stacks, [](const auto &a, const auto &b) { return a.back() > b.back(); }); ranges::sort(decreasing, ranges::greater{}); for (int j = 1; j < ssize(decreasing); ++j) { decreasing[j] += decreasing[j - 1]; } if (ssize(stacks) == 0) { cout << decreasing[k - 1] << "\n"; return 0; } long long res{}; { // rem = 0 int decreasingNum = k; long long stacksSum = 0; for (int i = 0;; ++i) { if (decreasingNum < 0) { break; } if (decreasingNum <= ssize(decreasing)) { auto decRes = decreasingNum == 0 ? 0 : decreasing[decreasingNum - 1]; long long tmpRes = decRes + stacksSum; if (tmpRes > res) { res = tmpRes; } } if (i == ssize(stacks)) { break; } decreasingNum -= m; stacksSum += stacks[i].back(); } } for (int rem = 1; rem < m; ++rem) { auto cmp = [&](const auto &a, const auto &b) { bool eq = stacks[a][rem - 1] == stacks[b][rem - 1]; if (eq) { return a > b; }; return stacks[a][rem - 1] > stacks[b][rem - 1]; }; set<long long, decltype(cmp)> prefixes(cmp); for (int i = 0; i < ssize(stacks); ++i) { prefixes.insert(i); } int prefix = *prefixes.begin(); int decreasingNum = k - rem; long long stacksSum = stacks[prefix][rem - 1]; for (int i = 0; i < ssize(stacks); ++i) { if (decreasingNum < 0) { break; } if (decreasingNum <= ssize(decreasing)) { auto decRes = decreasingNum == 0 ? 0 : decreasing[decreasingNum - 1]; auto tmpRes = decRes + stacksSum; if (tmpRes > res) { res = tmpRes; } } decreasingNum -= m; if (i == ssize(stacks) - 1) { break; } if (prefix > i) { stacksSum += stacks[i].back(); } else { auto c1 = stacksSum + stacks[i + 1].back(); auto newPrefix = *next(prefixes.begin()); // czy usunąć prefix auto c2 = stacksSum - stacks[prefix][rem - 1] + stacks[newPrefix][rem - 1] + stacks[i].back(); if (c2 > c1) { prefix = newPrefix; } stacksSum = max(c1, c2); } prefixes.erase(i); } } cout << res << "\n"; } |
English