제출 #1329194

#제출 시각아이디문제언어결과실행 시간메모리
1329194vlomaczkUplifting Excursion (BOI22_vault)C++20
100 / 100
1490 ms10196 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

ll M, L;

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	cin >> M >> L;
	ll n = 2*M + 1;
	vector<ll> a(n), c(n);
	for(ll i=0; i<n; ++i) cin >> a[i];
	c = a;
	ll sum = 0;
	for(ll i=0; i<n; ++i) sum += (i-M) * a[i];
	// cout << sum << "\n";

	//Compute the greedy (c[i] - taken by the greedy)
	ll took = 0;
	if(sum < L) {
		for(ll i=M; i<n; ++i) {
			took += (i-M) * a[i];
		}
		if(took < L) {
			cout << "impossible\n";
			return 0;
		}
		for(ll i=M-1; i>=0; --i) {
			if(took + (i-M) * a[i] >= L) {
				took += (i-M) * a[i];
			} else {
				c[i] = (took - L)/(M-i);
				took += (i-M) * ((took - L)/(M-i));
			}
		}
	} else {
		for(ll i=0; i<=M; ++i) {
			took += (i-M) * a[i];
		}
		if(took > L) {
			cout << "impossible\n";
			return 0;
		}
		for(ll i=M+1; i<n; ++i) {
			if(took + (i-M) * a[i] <= L) {
				took += (i-M) * a[i];
			} else {
				c[i] = (L-took)/(i-M);
				took += (i-M) * ((L-took)/(i-M));
			}
		}
	}
	// cout << took << "\n";
	ll cnt = 0;
	for(ll i=0; i<n; ++i) {
		cnt += c[i];
		// cout << c[i] << " ";
	}
	// cout << "\n";

	//Lower amount of items from M^2 to MlogM
	ll M2 = M*M; ll N = 2*M2 + 1;
	vector<vector<ll>> items(N);
	for(ll i=0; i<n; ++i) {	
		for(ll j=0; j<min(2*M+5, c[i]); ++j) items[M-i+M2].push_back(-1);
		for(ll j=0; j<min(2*M+5, a[i]-c[i]); ++j) items[i-M+M2].push_back(1);
	}
	// for(ll i=0; i<n; ++i) cout << c[i] << " "; cout << "\n";
	// for(ll i=0; i<n; ++i) cout << a[i]-c[i] << " "; cout << "\n";
	for(ll i=N-1; i>M2; --i) {
		if(items[i].size()==0) continue;
		vector<ll> ilev(2), Vv = {-1, 1};
		while(items[i].size()) {
			if(items[i].back()==-1) ilev[0]++;
			else ilev[1]++;
			items[i].pop_back();
		}
		for(ll k : {0,1}) {
			ll ile = ilev[k];
			ll W = i-M2; ll V = Vv[k];
			while(ile > 0 && abs(W) < abs(M2)) {
				ll dodaj = (ile%2 ? ile%2 : 2);
				if(abs(2*W) > abs(M2)) dodaj = min(3LL, ile);
				for(ll x=0; x<dodaj; ++x) items[W+M2].push_back(V);
				ile-=dodaj;
				ile/=2;
				V*=2; W*=2;
			}
		}
	}
	// cout << "xd\n"; return 0;
	for(ll i=0; i<M2; ++i) {
		if(items[i].size()==0) continue;
		vector<ll> ilev(2), Vv = {-1, 1};
		while(items[i].size()) {
			if(items[i].back()==-1) ilev[0]++;
			else ilev[1]++;
			items[i].pop_back();
		}
		for(ll k : {0,1}) {
			ll ile = ilev[k];
			ll W = i-M2; ll V = Vv[k];
			while(ile > 0 && abs(W) < abs(M2)) {
				ll dodaj = (ile%2 ? ile%2 : 2);
				if(abs(2*W) > abs(M2)) dodaj = min(3LL, ile);
				for(ll x=0; x<dodaj; ++x) items[W+M2].push_back(V);
				ile-=dodaj;
				ile/=2;
				V*=2; W*=2;
			}
		}
	}
	// cout << N << "\n";
	// for(ll i=0; i<N; ++i) { for(auto v : items[i]) cout << i-M2 << " " << v << "\n"; }

	//Regret the greedy using dp and fact that we can always mallaing the transition inside tha [L-M, L+M] and obtaining same weight twice can only worsen our solution (for prove look in editorial - https://www.boi2022.de/wp-content/uploads/2022/05/boi2022-day1-vault-spoiler.pdf)
	vector<ll> dp(N, -2e18);
	ll offset = L-M2;
	dp[took-offset] = cnt;
	auto add = [&](ll W, ll V) {
		vector<ll> ndp = dp;
		ll L = max(0LL, W);
		ll R = min(N-1, N-1+W);
		for(ll i=L; i<=R; ++i) {
			ndp[i] = max(dp[i], dp[i-W] + V);
		}
		swap(dp, ndp);	
	};
	for(ll i=0; i<N; ++i) {
		for(auto v : items[i]) add(i-M2, v);
	}
	if(dp[L - offset]<=0) cout << "impossible\n";
	else cout << dp[L-offset] << "\n";

	return 0;
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...