Submission #1275631

#TimeUsernameProblemLanguageResultExecution timeMemory
1275631NonozeSouvenirs (IOI25_souvenirs)C++20
100 / 100
38 ms424 KiB
#include "souvenirs.h"
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define sz(x) (int)x.size()
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define pb push_back
#define fi first
#define se second
#define cmin(a, b) a=min(a, b)
#define cmax(a, b) a=max(a, b)

int n;
vector<int> p, mini, maxi;

bool works(int x, int mid, pair<vector<signed>, int> &res, bool Minimize) {
	int valmin=mid, valmax=mid;
	bool ok=1;
	for (auto y: res.fi) {
		if (y<x) {
			if (mid+(x-y)>maxi[y]) ok=0;
			valmin+=max(mini[y], mid+(x-y));
			valmax+=maxi[y];
		}
		if (y>x) {
			if (mid-(y-x)<mini[y]) ok=0;
			valmin+=mini[y];
			valmax+=min(maxi[y], mid-(y-x));
		}
	}
	return ok && valmin<=res.se && res.se<=valmax;
}

void calc(int x, pair<vector<signed>, int> &res) {
	if (sz(res.fi)==1) {
		mini[x]=maxi[x]=res.se;
		return;
	}
	{ // calc mini
		int l=mini[x], r=maxi[x], ans=mini[x];
		while (l<=r) {
			int mid=(l+r)/2;
			if (works(x, mid, res, 1)) ans=mid, r=mid-1;
			else l=mid+1;
		}
		mini[x]=ans;
	}
	{ // calc maxi
		int l=mini[x], r=maxi[x], ans=maxi[x];
		while (l<=r) {
			int mid=(l+r)/2;
			if (works(x, mid, res, 0)) ans=mid, l=mid+1;
			else r=mid-1;
		}
		maxi[x]=ans;
	}
}

vector<pair<vector<signed>, int>> res;
vector<vector<int>> used;
void process(int id) {
	for (auto x: res[id].fi) {
		calc(x, res[id]);
		// cout << mini[x] << ' ' << maxi[x] << endl;
		if (mini[x]==maxi[x]) {
			// cout << x << endl;
			p[x]=mini[x];
			for (auto &y: used[x]) {
				res[y].se-=p[x];
				res[y].fi.erase(find(all(res[y].fi), x));
			}
			// for (int i=0; i<n; i++) {
			// 	cout << i << ' ' << mini[i] << ' ' << maxi[i] << ' ' << p[i] << endl;
			// }
			for (int i=0; i<x; i++) if (p[i]==-1) cmax(mini[i], p[x]+(x-i));
			for (int i=x+1; i<n; i++) if (p[i]==-1) cmin(maxi[i], p[x]-(i-x));
			for (auto &y: used[x]) process(y);
			used[x].clear();
			return;
		}
	}
}

void buy_souvenirs(signed N, long long P0) {
	n=N; p.resize(n, -1); p[0]=P0;
	vector<int> cnt(n, 0);
	mini.resize(n); maxi.resize(n); mini[0]=maxi[0]=P0;
	for (int i=1; i<n; i++) mini[i]=n-i, maxi[i]=P0-i;
	used.resize(n);
	while (1) {
		int best=-1, bestv=-1;
		for (int i=1; i<n; i++) if (p[i]==-1) {
			if (maxi[i]<bestv || bestv==-1) bestv=maxi[i], best=i;
		}
		if (best==-1) break;
		int i=best;
		assert(cnt[i]<=i);
		// cout << i << ' ' << mini[i] << ' ' << maxi[i] << endl;
		auto r=transaction(maxi[i]);
		res.pb({{}, 0}); res.back().se=maxi[i]-r.se;
		for (auto x: r.fi) {
			cnt[x]++;
			assert(cnt[x]<=x);
			if (p[x]!=-1) {
				res.back().se-=p[x];
			} else {
				res.back().fi.pb(x);
				used[x].pb(sz(res)-1);
			}
		}
		if (r.fi.back()+1<n) cmax(mini.back(), r.se+1);
		for (int j=n-2; j>r.fi.back(); j--) cmax(mini[j], mini[j+1]+1);
		process(sz(res)-1);
	}
	for (int i=1; i<n; i++) {
		assert(cnt[i]<=i);
		if (cnt[i]==i) continue;
		// while (mini[i]<maxi[i]) {
		// 	cout << i << ' ' << mini[i] << ' ' << maxi[i] << endl;
		// 	if (cnt[i]>i) assert(0);
		// 	auto r=transaction(maxi[i]);
		// 	res.pb({{}, 0}); res.back().se=maxi[i]-r.se;
		// 	for (auto x: r.fi) {
		// 		cnt[x]++;
		// 		if (p[x]!=-1) {
		// 			res.back().se-=p[x];
		// 		} else {
		// 			res.back().fi.pb(x);
		// 			used[x].pb(sz(res)-1);
		// 		}
		// 	}
		// 	process(sz(res)-1);
		// }
		while (cnt[i]<i) cnt[i]++, transaction(p[i]);
	}
	return;
}
#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...