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
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

#define st first
#define nd second
#define pb push_back
#define all(a) a.begin(), a.end()
#define sz(a) int(a.size())
#define f(i, a, b) for (int i = a; i < b; i++)
#define rep(i, a) f(i, 0, a)
#define int ll
#define tv(a, x) for (auto& a : x)
#define DUZO 1000000000000000000LL
#define en "\n"
#define cn continue
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vii = vector<pii>;

void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    vvi a(n, vi(m));
    f(i, 0, n) f(j, 0, m) cin >> a[i][j];
    vi norm; //te ktore mozna normalnie brac
    vii to_sort;
    f(i, 0, n) {
        if (a[i][0] >= a[i].back()) {
            tv(ele, a[i]) norm.pb(ele);
        } else {
            int sm = 0;
            tv(ele, a[i]) sm += ele;
            to_sort.pb({sm, i});
        }
    }
    sort(all(norm));
    reverse(all(norm));
    sort(all(to_sort));
    reverse(all(to_sort));
    vi pref(sz(norm) + 1);
    pref[0] = 0;
    f(i, 0, sz(norm)) {
        pref[i + 1] = pref[i] + norm[i];
    }
    int ans = 0;
    if (sz(pref) > k) ans = pref[k];
    int ob = 0;
    f(i, 0, sz(to_sort)) {
        tv(ele, a[to_sort[i].nd]) ob += ele;
        if ((m * (i + 1)) <= k && (sz(pref) - 1) >= (k - (m * (i + 1)))) {
            ans = max(ans, ob + pref[k - (m * (i + 1))]);
        }
    }
    ob = 0;
    vector<multiset<int>> ri(m); //po prawej czesc
    vector<multiset<int>> le(m); //po lewej czesci do tego specjalnego przypdaku
    f(i, 0, sz(to_sort)) {
        int ind = to_sort[i].nd;
        int aktl = 0;
        f(j, 0, m) {
            aktl += a[ind][j];
            ri[j].insert(aktl);
        }
    }
    //ob to obecna suma tego prefiksu
    f(i, 0, sz(to_sort)) { //prefisk caly wziety ale bez i
        int ind = to_sort[i].nd;
        int sm = 0;
        tv(ele, a[ind]) sm += ele;
        int pre = 0;
        f(j, 0, m) {
            if ((i * m + j + 1) <= k && (sz(pref) - 1) >= (k - (i * m + j + 1))) {
                ans = max(ans, pref[k - (i * m + j + 1)] + ob + *prev(ri[j].end()));
            }
            pre += a[ind][j];
            ri[j].erase(ri[j].find(pre));
            le[j].insert(sm - pre);
        }
        ob += sm;
        f(j, 0, m) { //zostaje z dupy dodatkowe j w juz zawladnietym prefiksie
            int ps = i * m + j + 1;
            if (ps <= k && (sz(pref) - 1) >= (k - ps)) {
                ans = max(ans, ob - *le[j].begin() + pref[k - ps]);
            }
        }
    }
    cout << ans << en;
}

int32_t main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int q = 1;
    //cin >> q;
    while (q--) {
        solve();
    }
    return 0;
}