Submission #604163

#TimeUsernameProblemLanguageResultExecution timeMemory
604163gagik_2007Carnival Tickets (IOI20_tickets)C++17
67 / 100
697 ms85384 KiB
#include "tickets.h"
#include <iostream>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <algorithm>
#include <string>
using namespace std;

#define ff first
#define ss second

typedef long long ll;
typedef long double ld;

const ll INF = 1e18;
ll n, k, m;
vector<ll>mns, mxs, mns_, mxs_;
ll erkaranun[1507][1507];
ll cnt0[1507];
vector<pair<int, int>>d;
vector<int>os[1507], ls[1507];
int os_[1507], ls_[1507];
vector<vector<int>>ans;
vector<int>ap, am;
bool isap[1507];
bool isam[1507];
bool ismx[1507][1507];
bool ismn[1507][1507];
ll mxc[1507];
ll mnc[1507];
int mxi[1507], mni[1507];
ll dp[1507][1507];
ll DP[307][90007];

struct Ket {
	int i, j, val;
	Ket(int ii, int jj, int vl) {
		i = ii;
		j = jj;
		val = vl;
	}
	bool operator<(Ket other)const {
		return val < other.val;
	}
	bool operator==(Ket other)const {
		return val == other.val;
	}
	bool operator>(Ket other)const {
		return val > other.val;
	}
	friend ostream& operator<<(ostream& os, Ket val);
};

ostream& operator<<(ostream& os, Ket val) {
	os << val.i << " " << val.j << ": " << val.val << ";  ";
	return os;
}

vector<Ket>sax;
vector<vector<Ket>>s;

bool give_zero(int i, int r);

bool give_one(int i, int r) {
	if (ls_[i] == ls[i].size()) {
		give_zero(i, r);
		return false;
	}
	ans[i][ls[i][ls_[i]]] = r;
	ls_[i]++;
	return true;
}

bool give_zero(int i, int r) {
	if (os_[i] == os[i].size()) {
		give_one(i, r);
		return false;
	}
	cnt0[i]--;
	ans[i][os[i][os_[i]]] = r;
	os_[i]++;
	return true;
}

void give_max(int i, int r) {
	////cout << "-- " << i << " " << r << " " << mxc[i] << endl;
	mxc[i]--;
	for (int j = mxi[i] + 1; j < m; j++) {
		if (ismx[i][j]) {
			////cout << j << endl;
			mxi[i] = j;
			ans[i][j] = r;
			break;
		}
	}
}

void give_min(int i, int r) {
	////cout << "== " << i << " " << r << endl;
	mnc[i]--;
	for (int j = mni[i] + 1; j < m; j++) {
		if (!ismx[i][j]) {
			mni[i] = j;
			//////cout << j << " ";
			ans[i][j] = r;
			break;
		}
	}
}

ll find_answer(vector<ll>a) {
	ll ans = INF;
	for (int i = 0; i < a.size(); i++) {
		ll cur = 0;
		for (int j = 0; j < a.size(); j++) {
			cur += abs(a[i] - a[j]);
		}
		ans = min(ans, cur);
	}
	return ans;
}

ll find_maximum(int k, vector<vector<int>> x) {
	n = x.size();
	m = x[0].size();
	if (m == 1) {
		vector<ll>v;
		ans.resize(n);
		for (int i = 0; i < n; i++) {
			ans[i].resize(1, 0);
			v.push_back(x[i][0]);
		}
		allocate_tickets(ans);
		return find_answer(v);
	}
	if (k == 1) {
		mns.push_back(0);
		mxs.push_back(0);
		for (int i = 0; i < n; i++) {
			ll mn = INF, mx = 0;
			int mn_ = -1, mx_ = -1;
			for (int j = 0; j < m; j++) {
				if (x[i][j] < mn) {
					mn_ = j;
				}
				if (x[i][j] > mx) {
					mx_ = j;
				}
				mn = min(mn, x[i][j] * 1ll);
				mx = max(mx, x[i][j] * 1ll);
			}
			mns.push_back(mn);
			mxs.push_back(mx);
			mns_.push_back(mn_);
			mxs_.push_back(mx_);
		}
		for (int i = 1; i <= n; i++) {
			for (int j = 0; j <= i; j++) {
				if (j != 0 && j != i) {
					erkaranun[i][j] = max(erkaranun[i - 1][j] + mxs[i], erkaranun[i - 1][j - 1] - mns[i]);
				}
				else if (j == 0) {
					erkaranun[i][j] = erkaranun[i - 1][j] + mxs[i];
				}
				else {
					erkaranun[i][j] = erkaranun[i - 1][j - 1] - mns[i];
				}
			}
		}
		string s = "";
		int j = n / 2;
		for (int i = n; i > 0; i--) {
			if (j == i || (j != 0 && erkaranun[i - 1][j - 1] - mns[i] == erkaranun[i][j])) {
				s += '0';
				j--;
			}
			else {
				s += '1';
			}
		}
		reverse(s.begin(), s.end());
		ans.resize(n);
		for (int i = 0; i < n; i++) {
			ans[i].resize(m, -1);
		}
		for (int i = 0; i < n; i++) {
			if (s[i] == '0') {
				ans[i][mns_[i]] = 0;
			}
			else {
				ans[i][mxs_[i]] = 0;
			}
		}
		allocate_tickets(ans);
		return erkaranun[n][n / 2];
	}


	if (n <= 80 && m <= 80) {
		for (int i = 0; i < n; i++) {
			vector<Ket>v;
			s.push_back(v);
			for (int j = 0; j < m; j++) {
				Ket ket(i, j, x[i][j]);
				s[i].push_back(ket);
			}
			sort(s[i].begin(), s[i].end());
		}
		for (int i = 0; i < n; i++) {
			for (int pi = 0; pi <= k; pi++) {
				int si = k - pi;
				for (int j = 0; j < pi; j++) {
					dp[i][pi] -= s[i][j].val;
				}
				for (int j = m - 1; j > m - si - 1; j--) {
					dp[i][pi] += s[i][j].val;
				}
			}
		}
		for (int i = 0; i < n; i++) {
			for (int Pi = 0; Pi <= n / 2 * k; Pi++) {
				DP[i][Pi] = -INF;
				if (i == 0 && Pi <= k)DP[i][Pi] = dp[i][Pi];
				else if (i != 0 && Pi <= k * (i + 1)) {
					for (int pi = 0; pi <= min(k, Pi); pi++) {
						if (Pi - pi <= k * i)
						DP[i][Pi] = max(DP[i - 1][Pi - pi] + dp[i][pi], DP[i][Pi]);
					}
				}
				//cout << DP[i][Pi] << " ";
			}
			//cout << endl;
		}
		int Pi = n / 2 * k;
		for (int i = n - 1; i >= 0; i--) {
			if (i == 0) {
				int pi = Pi;
				int si = k - pi;
				for (int j = 0; j < pi; j++) {
					ismn[i][j] = true;
				}
				for (int j = m - 1; j > m - si - 1; j--) {
					ismx[i][j] = true;
				}
			}
			for (int pi = 0; pi <= k; pi++) {
				if (DP[i][Pi] == DP[i - 1][Pi - pi] + dp[i][pi]) {
					int si = k - pi;
					for (int j = 0; j < pi; j++) {
						ismn[i][j] = true;
					}
					for (int j = m - 1; j > m - si - 1; j--) {
						ismx[i][j] = true;
					}
					Pi -= pi;
					break;
				}
			}
		}

		ans.resize(n);
		for (int i = 0; i < n; i++) {
			ans[i].resize(m, -1);
		}
		mns.push_back(0);
		mxs.push_back(0);
		for (int i = 0; i < n; i++) {
			mni[i] = -1;
			mxi[i] = -1;
			ll mn = INF, mx = 0;
			int mn_ = -1, mx_ = -1;
			for (int j = 0; j < m; j++) {
				Ket ket(i, j, x[i][j]);
				sax.push_back(ket);
				if (x[i][j] < mn) {
					mn_ = j;
				}
				if (x[i][j] > mx) {
					mx_ = j;
				}
				mn = min(mn, x[i][j] * 1ll);
				mx = max(mx, x[i][j] * 1ll);
			}
			mns.push_back(mn);
			mxs.push_back(mx);
			mns_.push_back(mn_);
			mxs_.push_back(mx_);
		}
		sort(sax.begin(), sax.end());
		ll res = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (ismn[i][j]) {
					res -= s[i][j].val;
				}
				if (ismx[i][j]) {
					res += s[i][j].val;
				}
			}
		}
		for (int i = 0; i < n; i++) {
			bool is_ap = true;
			bool is_am = true;
			for (int j = 0; j < m; j++) {
				if (ismx[i][j]) {
					is_ap = false;
				}
				if (ismn[i][j]) {
					is_am = false;
				}
			}
			if (is_am) {
				am.push_back(i);
				isam[i] = true;
			}
			else if (is_ap) {
				ap.push_back(i);
				isap[i] = true;
			}
			else {
				for (int j = 0; j < m; j++) {
					if (ismx[i][j]) {
						mxc[i]++;
					}
					if (ismn[i][j]) {
						mnc[i]++;
					}
				}
			}
		}
		////cout << "-> " << ap.size() << " " << am.size() << endl;
		//////cout << ap[0] << endl;
		for (int r = 0; r < k; r++) {
			for (int tox : am) {
				give_max(tox, r);
			}
			int cnt = 0;
			for (int tox : ap) {
				give_min(tox, r);
				cnt++;
			}
			int len = m - r - 1;
			for (int tox = 0; tox < n; tox++) {
				if (!isap[tox] && !isam[tox]) {
					if (cnt < n / 2) {
						give_min(tox, r);
						if (mnc[tox] == 0) {
							isam[tox] = true;
							am.push_back(tox);
						}
						cnt++;
					}
					else {
						give_max(tox, r);
						if (mxc[tox] == 0) {
							isap[tox] = true;
							ap.push_back(tox);
						}
					}
				}
			}
		}
		allocate_tickets(ans);
		return res;
	}



	if (m == k) {
		ans.resize(n);
		for (int i = 0; i < n; i++) {
			ans[i].resize(m, -1);
		}
		mns.push_back(0);
		mxs.push_back(0);
		for (int i = 0; i < n; i++) {
			mni[i] = -1;
			mxi[i] = -1;
			ll mn = INF, mx = 0;
			int mn_ = -1, mx_ = -1;
			for (int j = 0; j < m; j++) {
				Ket ket(i, j, x[i][j]);
				sax.push_back(ket);
				if (x[i][j] < mn) {
					mn_ = j;
				}
				if (x[i][j] > mx) {
					mx_ = j;
				}
				mn = min(mn, x[i][j] * 1ll);
				mx = max(mx, x[i][j] * 1ll);
			}
			mns.push_back(mn);
			mxs.push_back(mx);
			mns_.push_back(mn_);
			mxs_.push_back(mx_);
		}
		sort(sax.begin(), sax.end());
		ll res = 0;
		for (int i = 0; i < sax.size() / 2; i++) {
			ismn[sax[i].i][sax[i].j] = true;
			res -= sax[i].val;
		}
		for (int i = sax.size() / 2; i < sax.size(); i++) {
			ismx[sax[i].i][sax[i].j] = true;
			////cout << sax[i].i << " " << sax[i].j << endl;
			res += sax[i].val;
		}
		for (int i = 0; i < n; i++) {
			bool is_ap = true;
			bool is_am = true;
			for (int j = 0; j < m; j++) {
				if (ismx[i][j]) {
					is_ap = false;
				}
				if (ismn[i][j]) {
					is_am = false;
				}
			}
			if (is_am) {
				am.push_back(i);
				isam[i] = true;
			}
			else if (is_ap) {
				ap.push_back(i);
				isap[i] = true;
			}
			else {
				for (int j = 0; j < m; j++) {
					if (ismx[i][j]) {
						mxc[i]++;
					}
					if (ismn[i][j]) {
						mnc[i]++;
					}
				}
			}
		}
		////cout << "-> " << ap.size() << " " << am.size() << endl;
		//////cout << ap[0] << endl;
		for (int r = 0; r < k; r++) {
			for (int tox : am) {
				give_max(tox, r);
			}
			int cnt = 0;
			for (int tox : ap) {
				give_min(tox, r);
				cnt++;
			}
			int len = m - r - 1;
			for (int tox = 0; tox < n; tox++) {
				if (!isap[tox] && !isam[tox]) {
					if (cnt < n / 2) {
						give_min(tox, r);
						if (mnc[tox] == 0) {
							isam[tox] = true;
							am.push_back(tox);
						}
						cnt++;
					}
					else {
						give_max(tox, r);
						if (mxc[tox] == 0) {
							isap[tox] = true;
							ap.push_back(tox);
						}
					}
				}
			}
		}
		allocate_tickets(ans);
		return res;
	}


	if (n <= 80 && m <= 80) {

	}


	else {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				cnt0[i] += (x[i][j] == 0);
				if (x[i][j] == 0) {
					os[i].push_back(j);
				}
				else {
					ls[i].push_back(j);
				}
			}
		}
		ans.resize(n);
		for (int i = 0; i < n; i++) {
			ans[i].resize(m, -1);
		}
		ll res = 0;
		for (int r = 0; r < k; r++) {
			for (int i = 0; i < n; i++) {
				d.push_back({ cnt0[i],i });
			}
			sort(d.begin(), d.end());
			/*for (auto x : d) {
				////cout << x.ff << " " << x.ss << "  ";
			}
			////cout << endl;*/
			ll cnt = 0;
			for (int i = 0; i < n / 2; i++) {
				cnt += give_one(d[i].ss, r);
			}
			for (int i = n / 2; i < n; i++) {
				cnt += !give_zero(d[i].ss, r);
			}
			res += min(cnt, n - cnt);
			//////cout << res << " ";
			d.clear();
		}
		allocate_tickets(ans);
		return res;
	}
}

/*
3 1 1 1 2 3

4 4 4 1 1 1 0 1 0 0 1 0 0 0 1 1 1 0 1
7
4 4 4 5 8 6 9 4 1 5 2 3 6 5 7 8 4 5 9
29
5 5 5 1 2 3 6 5 4 8 5 2 7 9 4 5 8 9 5 6 4 8 4 2 5 1 4 6
69
5 5 4 1 2 3 6 5 4 8 5 2 7 9 4 5 8 9 5 6 4 8 4 2 5 1 4 6
4 4 4 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4
4 4 4 1 2 1 2 1 2 1 2 3 4 3 4 3 4 3 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 5 4 4 4 5 4 4 4 5 4 4 4 5
4 4 4 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8

5
*/

Compilation message (stderr)

tickets.cpp: In function 'bool give_one(int, int)':
tickets.cpp:67:13: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   67 |  if (ls_[i] == ls[i].size()) {
      |      ~~~~~~~^~~~~~~~~~~~~~~
tickets.cpp: In function 'bool give_zero(int, int)':
tickets.cpp:77:13: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   77 |  if (os_[i] == os[i].size()) {
      |      ~~~~~~~^~~~~~~~~~~~~~~
tickets.cpp: In function 'll find_answer(std::vector<long long int>)':
tickets.cpp:115:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  115 |  for (int i = 0; i < a.size(); i++) {
      |                  ~~^~~~~~~~~~
tickets.cpp:117:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  117 |   for (int j = 0; j < a.size(); j++) {
      |                   ~~^~~~~~~~~~
tickets.cpp: In function 'll find_maximum(int, std::vector<std::vector<int> >)':
tickets.cpp:344:8: warning: unused variable 'len' [-Wunused-variable]
  344 |    int len = m - r - 1;
      |        ^~~
tickets.cpp:402:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<Ket>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  402 |   for (int i = 0; i < sax.size() / 2; i++) {
      |                   ~~^~~~~~~~~~~~~~~~
tickets.cpp:406:34: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<Ket>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  406 |   for (int i = sax.size() / 2; i < sax.size(); i++) {
      |                                ~~^~~~~~~~~~~~
tickets.cpp:452:8: warning: unused variable 'len' [-Wunused-variable]
  452 |    int len = m - r - 1;
      |        ^~~
tickets.cpp:523:1: warning: control reaches end of non-void function [-Wreturn-type]
  523 | }
      | ^
#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...