#pragma GCC optimize("O3,inline,unroll-loops")
#include "bits/stdc++.h"
using namespace std;
#define rep(i,a,b) for(int i=(a); i<(b); ++i)
#define all(x) x.begin(),x.end()
#define sz(x) int(x.size())
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
// stolen from nachia on librarychecker, and modified to long long / max
inline vector<ll> mpconv(const vector<ll>& a, const vector<ll>& b){
int n = a.size();
int m = b.size();
int z = n + m - 1;
vector<ll> c(z);
vi idx(z+1);
c[0] = a[0] + b[0];
idx.back() = m-1;
int d = 1; while(d < z) d *= 2;
for(int q=d/2; q>0; q/=2){
for(int h=q; h<z; h+=q*2){
int l = h-q, r = min(h+q, z);
idx[h] = idx[l];
for(int t=idx[l]; t<=idx[r]; t++){
if(t<=h && h-t<n && c[h] < b[t] + a[h-t]){
c[h] = b[t] + a[h-t];
idx[h] = t;
}
}
}
}
return c;
}
vector<vector<ll>> handle(const vector<vector<ll>>& L, const vector<vector<ll>>& R) {
vector<vector<ll>> ans(sz(L));
rep(i,0,sz(L)){
ans[i] = mpconv(L[0], R[i]);
}
return ans;
}
int main(){
cin.tie(NULL),ios::sync_with_stdio(false);
int n,m,k; cin >> n >> m >> k;
vector<ll> bottoms;
vector<vector<ll>> tops;
rep(i,0,n){
vector<ll> a(m);
for(auto& c : a) cin >> c;
if (a.back() > a[0]) {
tops.push_back(a);
}else{
bottoms.insert(end(bottoms),all(a));
}
}
sort(all(bottoms), greater<ll>());
rep(i,0,sz(bottoms)-1) bottoms[i+1] += bottoms[i];
bottoms.insert(begin(bottoms),0);
auto rec = [&](int l, int r, auto&& rec) -> vector<vector<ll>> {
if (l == r){
vector<vector<ll>> ans(m);
ans[0] = {0};
return ans;
} else if (l+1 == r) {
vector<vector<ll>> ans(m);
ans[0] = {0ll, accumulate(all(tops[l]),0ll)};
rep(i,1,m) ans[i] = {ans[i-1][0] + tops[l][i-1]};
return ans;
}
int mid = (l+r)/2;
auto L = rec(l,mid,rec), R = rec(mid,r,rec);
auto ans = handle(L,R), ans2 = handle(R,L);
rep(i,0,m) rep(j,0,sz(ans[i])) ans[i][j] = max(ans[i][j], ans2[i][j]);
return ans;
};
auto ret = rec(0,sz(tops),rec);
ll ans = 0;
rep(take,0,k+1) {
if (k-take < sz(bottoms) and take/m < sz(ret[take%m])) {
ans = max(ans, bottoms[k-take] + ret[take%m][take/m]);
}
}
cout << ans << '\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 | #pragma GCC optimize("O3,inline,unroll-loops") #include "bits/stdc++.h" using namespace std; #define rep(i,a,b) for(int i=(a); i<(b); ++i) #define all(x) x.begin(),x.end() #define sz(x) int(x.size()) typedef long long ll; typedef unsigned long long ull; typedef vector<int> vi; typedef vector<vi> vvi; // stolen from nachia on librarychecker, and modified to long long / max inline vector<ll> mpconv(const vector<ll>& a, const vector<ll>& b){ int n = a.size(); int m = b.size(); int z = n + m - 1; vector<ll> c(z); vi idx(z+1); c[0] = a[0] + b[0]; idx.back() = m-1; int d = 1; while(d < z) d *= 2; for(int q=d/2; q>0; q/=2){ for(int h=q; h<z; h+=q*2){ int l = h-q, r = min(h+q, z); idx[h] = idx[l]; for(int t=idx[l]; t<=idx[r]; t++){ if(t<=h && h-t<n && c[h] < b[t] + a[h-t]){ c[h] = b[t] + a[h-t]; idx[h] = t; } } } } return c; } vector<vector<ll>> handle(const vector<vector<ll>>& L, const vector<vector<ll>>& R) { vector<vector<ll>> ans(sz(L)); rep(i,0,sz(L)){ ans[i] = mpconv(L[0], R[i]); } return ans; } int main(){ cin.tie(NULL),ios::sync_with_stdio(false); int n,m,k; cin >> n >> m >> k; vector<ll> bottoms; vector<vector<ll>> tops; rep(i,0,n){ vector<ll> a(m); for(auto& c : a) cin >> c; if (a.back() > a[0]) { tops.push_back(a); }else{ bottoms.insert(end(bottoms),all(a)); } } sort(all(bottoms), greater<ll>()); rep(i,0,sz(bottoms)-1) bottoms[i+1] += bottoms[i]; bottoms.insert(begin(bottoms),0); auto rec = [&](int l, int r, auto&& rec) -> vector<vector<ll>> { if (l == r){ vector<vector<ll>> ans(m); ans[0] = {0}; return ans; } else if (l+1 == r) { vector<vector<ll>> ans(m); ans[0] = {0ll, accumulate(all(tops[l]),0ll)}; rep(i,1,m) ans[i] = {ans[i-1][0] + tops[l][i-1]}; return ans; } int mid = (l+r)/2; auto L = rec(l,mid,rec), R = rec(mid,r,rec); auto ans = handle(L,R), ans2 = handle(R,L); rep(i,0,m) rep(j,0,sz(ans[i])) ans[i][j] = max(ans[i][j], ans2[i][j]); return ans; }; auto ret = rec(0,sz(tops),rec); ll ans = 0; rep(take,0,k+1) { if (k-take < sz(bottoms) and take/m < sz(ret[take%m])) { ans = max(ans, bottoms[k-take] + ret[take%m][take/m]); } } cout << ans << '\n'; } |
English