#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<vector<ll>> stacks;
vector<bool> isInc;
vector<ll> decreasing;
vector<pair<ll, int>> increasing;
vector<ll> decreasingOdp, increasingOdp, suffSum;
void sortBuckets(int n, int m){
for(int i = 0 ; i < n ; i++){
if(isInc[i]) increasing.push_back({0, i});
for(int j = 0 ; j < m ; j++){
if(isInc[i]) increasing.back().first += stacks[i][j];
else decreasing.push_back(stacks[i][j]);
}
}
sort(decreasing.begin(), decreasing.end(), greater<ll>());
sort(increasing.begin(), increasing.end(), greater<pair<ll, int>>());
}
void calcIncreasingOdp(int n, int m, int suff, int k){
ll sum = 0, minimum = 1e18;
int cnt = 0;
vector<ll> prefSum(n + 1);
for(int i = 1 ; i <= (int)increasing.size() ; i++){
prefSum[i] = prefSum[i - 1] + increasing[i - 1].first;
}
for(int i = 0 ; i < (int)increasing.size() && (i + 1) * m - suff <= k ; i++){
sum += increasing[i].first;
while(cnt < (int)increasing.size() && increasing[cnt].first == increasing[i].first){
minimum = min(minimum, suffSum[cnt]);
cnt++;
}
increasingOdp[(i + 1) * m - suff] = max(sum - minimum, increasingOdp[(i + 1) * m - suff]);
}
ll maximum = 0;
for(int i = increasing.size() - 1 ; i >= 0 ; i--){
sum = prefSum[i];
maximum = max(maximum, increasing[i].first - suffSum[i]);
if((i + 1) * m - suff <= k){
increasingOdp[(i + 1) * m - suff] = max(increasingOdp[(i + 1) * m - suff], sum + maximum);
}
}
}
ll solve(int n, int m, int k){
sortBuckets(n, m);
for(int i = 1 ; i <= min(k, (int)decreasing.size()) ; i++) decreasingOdp[i] = decreasingOdp[i - 1] + decreasing[i - 1];
suffSum.resize(n);
for(int i = 0 ; i < m ; i++){
for(int j = 0 ; j < (int)increasing.size() ; j++){
suffSum[j] += stacks[increasing[j].second][m - i];
}
calcIncreasingOdp(n, m, i, k);
}
ll ans = 0;
for(int i = 0 ; i <= k ; i++){
ans = max(ans, increasingOdp[i] + decreasingOdp[k - i]);
}
return ans;
}
int main(){
cin.tie(0);
ios_base::sync_with_stdio(0);
int n, m, k;
cin >> n >> m >> k;
increasingOdp.resize(k + 1);
decreasingOdp.resize(k + 1);
stacks.resize(n);
isInc.resize(n);
for(int i = 0 ; i < n ; i++){
stacks[i].resize(m + 1);
for(int j = 0 ; j < m ; j++){
cin >> stacks[i][j];
if(j > 0) isInc[i] = (isInc[i] | (stacks[i][j - 1] < stacks[i][j]));
}
}
cout << solve(n, m, k) << '\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 | #include<bits/stdc++.h> using namespace std; typedef long long ll; vector<vector<ll>> stacks; vector<bool> isInc; vector<ll> decreasing; vector<pair<ll, int>> increasing; vector<ll> decreasingOdp, increasingOdp, suffSum; void sortBuckets(int n, int m){ for(int i = 0 ; i < n ; i++){ if(isInc[i]) increasing.push_back({0, i}); for(int j = 0 ; j < m ; j++){ if(isInc[i]) increasing.back().first += stacks[i][j]; else decreasing.push_back(stacks[i][j]); } } sort(decreasing.begin(), decreasing.end(), greater<ll>()); sort(increasing.begin(), increasing.end(), greater<pair<ll, int>>()); } void calcIncreasingOdp(int n, int m, int suff, int k){ ll sum = 0, minimum = 1e18; int cnt = 0; vector<ll> prefSum(n + 1); for(int i = 1 ; i <= (int)increasing.size() ; i++){ prefSum[i] = prefSum[i - 1] + increasing[i - 1].first; } for(int i = 0 ; i < (int)increasing.size() && (i + 1) * m - suff <= k ; i++){ sum += increasing[i].first; while(cnt < (int)increasing.size() && increasing[cnt].first == increasing[i].first){ minimum = min(minimum, suffSum[cnt]); cnt++; } increasingOdp[(i + 1) * m - suff] = max(sum - minimum, increasingOdp[(i + 1) * m - suff]); } ll maximum = 0; for(int i = increasing.size() - 1 ; i >= 0 ; i--){ sum = prefSum[i]; maximum = max(maximum, increasing[i].first - suffSum[i]); if((i + 1) * m - suff <= k){ increasingOdp[(i + 1) * m - suff] = max(increasingOdp[(i + 1) * m - suff], sum + maximum); } } } ll solve(int n, int m, int k){ sortBuckets(n, m); for(int i = 1 ; i <= min(k, (int)decreasing.size()) ; i++) decreasingOdp[i] = decreasingOdp[i - 1] + decreasing[i - 1]; suffSum.resize(n); for(int i = 0 ; i < m ; i++){ for(int j = 0 ; j < (int)increasing.size() ; j++){ suffSum[j] += stacks[increasing[j].second][m - i]; } calcIncreasingOdp(n, m, i, k); } ll ans = 0; for(int i = 0 ; i <= k ; i++){ ans = max(ans, increasingOdp[i] + decreasingOdp[k - i]); } return ans; } int main(){ cin.tie(0); ios_base::sync_with_stdio(0); int n, m, k; cin >> n >> m >> k; increasingOdp.resize(k + 1); decreasingOdp.resize(k + 1); stacks.resize(n); isInc.resize(n); for(int i = 0 ; i < n ; i++){ stacks[i].resize(m + 1); for(int j = 0 ; j < m ; j++){ cin >> stacks[i][j]; if(j > 0) isInc[i] = (isInc[i] | (stacks[i][j - 1] < stacks[i][j])); } } cout << solve(n, m, k) << '\n'; } |
English