Submission #1333721

#TimeUsernameProblemLanguageResultExecution timeMemory
1333721gohchingjaykIMO (EGOI25_imo)C++20
38 / 100
301 ms17200 KiB
#pragma GCC optimize("O3,inline")
#include <bits/stdc++.h>
 
using namespace std;
 
using ll = long long;
#define int ll

using ii = pair<int, int>;
using iii = pair<int, ii>;
using pvii = pair<vector<int>, ii>;
 
constexpr int MAXN = 20000 + 5;
constexpr int INF = 1e18 + 5;
constexpr int LOG = 20;

signed main() {
	ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	
	int N, M, K; cin >> N >> M >> K;

	vector<pvii> inp(N);
	for (int i = 0; i < N; ++i) {
		vector<int> lol(M); for (int j = 0; j < M; ++j) cin >> lol[j];
		sort(lol.begin(), lol.end());
		int s = 0; for (int j = 0; j < M; ++j) s += lol[j];
		inp[i] = pvii{lol, ii{s, i}};
	}
	
	sort(inp.begin(), inp.end(), [&](const pvii &a, const pvii &b) {
		return a.second.first < b.second.first || a.second.first == b.second.first && a.second.second > b.second.second;
	});
	
	if (N * M <= 16) {
  	int best = N * M;
  	for (int m = 0; m < (1 << (N * M)); ++m) {
  		vector<pvii> inp2;
  		vector<int> order;
  		for (int i = 0; i < N; ++i) {
  			vector<int> waa0;
  			vector<int> waa1;
  			for (int j = 0; j < M; ++j) {
  				if ((m >> (i * M + j)) & 1) {
  					waa0.emplace_back(0);
  					waa1.emplace_back(K);
  				}
  				else {
  					waa0.emplace_back(inp[i].first[j]);
  					waa1.emplace_back(inp[i].first[j]);
  				}
  			}
  			
  			order.emplace_back(inp[i].second.second);
  			order.emplace_back(inp[i].second.second);
  			
  			sort(waa0.begin(), waa0.end());
  			sort(waa1.begin(), waa1.end());
  			int s0 = 0; for (int x : waa0) s0 += x;
  			int s1 = 0; for (int x : waa1) s1 += x;
  			inp2.emplace_back(pvii{waa0, ii{s0, inp[i].second.second}});
  			inp2.emplace_back(pvii{waa1, ii{s1, inp[i].second.second}});
  		}
  		
  		sort(inp2.begin(), inp2.end(), [&](const pvii &a, const pvii &b) {
  			return a.second.first < b.second.first || a.second.first == b.second.first && a.second.second > b.second.second;
  		});
  		
  		bool good = true;
  		for (int i = 0; i < 2 * N; ++i) {
  			if (inp2[i].second.second != order[i]) good = false;
  		}
  		
  		if (good) best = min(best, N * M - __builtin_popcountll(m));
  	}
  	
  	cout << best;
	  exit(0);
	}
	
	int ans = N * M;
	int prevMax = 0;
	for (int i = 0; i < N; ++i) {
		int nextVal = (i == N-1 ? K * M : inp[i+1].second.first - (inp[i+1].second.second > inp[i].second.second));
		vector<int> &v = inp[i].first;
		int s = inp[i].second.first;
		int idx = inp[i].second.second;
		int lastIdx = (i ? inp[i-1].second.second : INF);
		if (idx > lastIdx) prevMax++;
		
		int remCtr1 = 0;
		int ps = s;
		for (int j = 0; j < M; ++j) {
			if (ps - v[j] >= prevMax) {
				ps -= v[j]; remCtr1++;
			}
		}
		
		int remCtr2 = 0;
		ps = s;
		for (int j = M-1; j >= 0; --j) {
			if (ps - v[j] + K <= nextVal) {
				ps = ps - v[j] + K; remCtr2++;
			}
		}
		
		int maxRem = min(remCtr1, remCtr2);
		
		if (!maxRem) {
			prevMax = s;
			//cout << "0" << '\n';
			continue;
		}
		
		vector<bitset<105>> dp_prev(maxRem + 1);
		vector<bitset<105>> dp_curr(maxRem + 1);
		dp_curr[0].set(0);
		
		for (int j = 0; j < M; ++j) {
			swap(dp_curr, dp_prev);
			for (int k = 0; k <= maxRem; ++k) dp_curr[k] = dp_prev[k] << v[j];
			for (int k = 1; k <= maxRem; ++k) dp_curr[k] |= dp_prev[k-1];
		}
		
		[&]() {
			for (int k = maxRem; k > 0; --k) {
				for (int j = prevMax; j <= nextVal - k * K; ++j) {
					if (dp_curr[k][j]) {
						ans -= k;
						//cout << k << ' ' << j << '\n';
						prevMax = j + k * K;
						return;
					}
				}
			}
			prevMax = s;
			//cout << "0" << '\n';
		}();
	}
	
	cout << ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...