//Solution by Mikołaj Kołek
#include "bits/stdc++.h"
#define intin *istream_iterator<int>(cin)
using namespace std;
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int n = intin, m = intin, k = intin;
vector<deque<long long>> increasing, decreasing;
for(int i = 0; i < n; i++) {
deque<long long> stack(m);
copy_n(istream_iterator<long long>(cin), m, stack.begin());
bool isDecreasing = true;
for(int i = 1; i < m; i++) {
if(stack[i] > stack[i - 1]) {
isDecreasing = false;
break;
}
if(stack[i] < stack[i - 1])
break;
}
if(isDecreasing)
decreasing.push_back(stack);
else
increasing.push_back(stack);
}
vector<long long> increasingRes(k + 1, -1e18), decreasingRes(k + 1, -1e18);
increasingRes[0] = decreasingRes[0] = 0;
{
// Calculations for decreasing
priority_queue<pair<long long, int>> Q;
for(int i = 0; i < decreasing.size(); i++) {
Q.push({ decreasing[i][0], i });
decreasing[i].pop_front();
}
int decIdx = 1;
while(!Q.empty()) {
auto [largest, largestIdx] = Q.top(); Q.pop();
if(decIdx <= k) {
decreasingRes[decIdx] = decreasingRes[decIdx - 1] + largest;
decIdx++;
}
else
break;
if(!decreasing[largestIdx].empty()) {
Q.push({ decreasing[largestIdx].front(), largestIdx });
decreasing[largestIdx].pop_front();
}
}
}
{
// Calculations for increasing
long long sumOfAll = 0;
vector<pair<long long, int>> sums;
for(int i = 0; i < increasing.size(); i++) {
long long sum = accumulate(increasing[i].begin(), increasing[i].end(), 0LL);
sums.push_back({ sum, i });
sumOfAll += sum;
}
sort(sums.begin(), sums.end());
long long sumOfSuffix = sumOfAll;
vector<long long> positionalSums(m + 1);
for(int i = 0; i < increasing.size(); i++) {
auto [currentSum, currentIdx] = sums[i];
sumOfSuffix -= currentSum;
long long prefSum = 0;
for(int j = 0; j <= m; j++) {
if(j != 0) {
prefSum += increasing[currentIdx][j - 1];
positionalSums[j] = max(positionalSums[j], prefSum);
}
int sumPos = ((increasing.size() - i - 1) * m) + j;
long long sum = sumOfSuffix + positionalSums[j];
if(sumPos <= k)
increasingRes[sumPos] = max(increasingRes[sumPos], sum);
}
}
long long sumOfPrefix = 0;
reverse(sums.begin(), sums.end());
vector<long long> minSuffixes(m, LLONG_MAX);
for(int i = 0; i < sums.size(); i++) {
auto [currentSum, currentIdx] = sums[i];
sumOfPrefix += currentSum;
long long sufSum = 0;
for(int j = m - 1; j >= 0; j--) {
sufSum += increasing[currentIdx][j];
minSuffixes[j] = min(minSuffixes[j], sufSum);
int sumPos = (i * m) + j;
long long sum = sumOfPrefix - minSuffixes[j];
if(sumPos <= k)
increasingRes[sumPos] = max(increasingRes[sumPos], sum);
}
}
}
long long res = 0;
for(int i = 0; i <= k; i++)
res = max(res, increasingRes[i] + decreasingRes[k - i]);
cout << res;
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 | //Solution by Mikołaj Kołek #include "bits/stdc++.h" #define intin *istream_iterator<int>(cin) using namespace std; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n = intin, m = intin, k = intin; vector<deque<long long>> increasing, decreasing; for(int i = 0; i < n; i++) { deque<long long> stack(m); copy_n(istream_iterator<long long>(cin), m, stack.begin()); bool isDecreasing = true; for(int i = 1; i < m; i++) { if(stack[i] > stack[i - 1]) { isDecreasing = false; break; } if(stack[i] < stack[i - 1]) break; } if(isDecreasing) decreasing.push_back(stack); else increasing.push_back(stack); } vector<long long> increasingRes(k + 1, -1e18), decreasingRes(k + 1, -1e18); increasingRes[0] = decreasingRes[0] = 0; { // Calculations for decreasing priority_queue<pair<long long, int>> Q; for(int i = 0; i < decreasing.size(); i++) { Q.push({ decreasing[i][0], i }); decreasing[i].pop_front(); } int decIdx = 1; while(!Q.empty()) { auto [largest, largestIdx] = Q.top(); Q.pop(); if(decIdx <= k) { decreasingRes[decIdx] = decreasingRes[decIdx - 1] + largest; decIdx++; } else break; if(!decreasing[largestIdx].empty()) { Q.push({ decreasing[largestIdx].front(), largestIdx }); decreasing[largestIdx].pop_front(); } } } { // Calculations for increasing long long sumOfAll = 0; vector<pair<long long, int>> sums; for(int i = 0; i < increasing.size(); i++) { long long sum = accumulate(increasing[i].begin(), increasing[i].end(), 0LL); sums.push_back({ sum, i }); sumOfAll += sum; } sort(sums.begin(), sums.end()); long long sumOfSuffix = sumOfAll; vector<long long> positionalSums(m + 1); for(int i = 0; i < increasing.size(); i++) { auto [currentSum, currentIdx] = sums[i]; sumOfSuffix -= currentSum; long long prefSum = 0; for(int j = 0; j <= m; j++) { if(j != 0) { prefSum += increasing[currentIdx][j - 1]; positionalSums[j] = max(positionalSums[j], prefSum); } int sumPos = ((increasing.size() - i - 1) * m) + j; long long sum = sumOfSuffix + positionalSums[j]; if(sumPos <= k) increasingRes[sumPos] = max(increasingRes[sumPos], sum); } } long long sumOfPrefix = 0; reverse(sums.begin(), sums.end()); vector<long long> minSuffixes(m, LLONG_MAX); for(int i = 0; i < sums.size(); i++) { auto [currentSum, currentIdx] = sums[i]; sumOfPrefix += currentSum; long long sufSum = 0; for(int j = m - 1; j >= 0; j--) { sufSum += increasing[currentIdx][j]; minSuffixes[j] = min(minSuffixes[j], sufSum); int sumPos = (i * m) + j; long long sum = sumOfPrefix - minSuffixes[j]; if(sumPos <= k) increasingRes[sumPos] = max(increasingRes[sumPos], sum); } } } long long res = 0; for(int i = 0; i <= k; i++) res = max(res, increasingRes[i] + decreasingRes[k - i]); cout << res; return 0; } |
English