제출 #78354

#제출 시각아이디문제언어결과실행 시간메모리
78354shoemakerjo전선 연결 (IOI17_wiring)C++14
100 / 100
93 ms86540 KiB
#include "wiring.h"
#include <bits/stdc++.h>

using namespace std;
#define prev previousguy
#define ll long long
#define maxn 100010
#define pii pair<int, int>

ll dp[2][maxn];

int prev, cur;
int n, m;
const ll inf = 1LL << 62;
vector<pii> stuff;
ll suf[maxn];
ll pref[maxn];

ll min_total_length(vector<int> r, vector<int> b) {
	n = r.size();
	m = b.size();

	cur = 0; prev = 1;
	
	for (int i = 0; i < n; i++) {
		stuff.push_back(pii(r[i],  0));
	}
	for (int i = 0; i < m; i++) {
		stuff.push_back(pii(b[i], 1));
	}
	sort(stuff.begin(), stuff.end());

	int lastsize = -1;
	for (int i = 0; i < n+m; i++) {
		int cstart = i;
		int cend = i;
		while (cend < n + m - 1 && stuff[cend+1].second == stuff[cend].second) 
			++cend;

		// cout << "group from " << cstart << " " << cend << endl;

		swap(prev, cur);
		int csize = cend - cstart+1;

		if (lastsize == -1) {
			dp[cur][0] = 0;
			for (int j = 1; j <= csize; j++) dp[cur][j] = inf;
		}
		else {
			ll gap = stuff[cstart].first - stuff[cstart-1].first;

			// cout << "GAP: " << gap << endl;

			int oend = cstart-1;
			//do suffix for how many we take
			suf[0] = 0;
			for (int j = 1; j <= lastsize; j++) {
				suf[j] = suf[j-1] + stuff[oend].first - 
					stuff[oend-j+1].first;
			}
			pref[0] = 0; //prefix for how many we take
			for (int j = 1; j <= csize; j++) {
				pref[j] = pref[j-1] + stuff[cstart+j-1].first - 
					stuff[cstart].first;
			}

			for (int j = 0; j <= csize; j++) {
				dp[cur][j] = inf;
			}

			//do minimum from the left
			ll curmin = inf;
			for (int j = 0; j <= csize; j++) {
				//consider taking less than me from the left to connect
				if (lastsize - j >= 0) 
					curmin = min(curmin, dp[prev][lastsize-j] + suf[j]);

				dp[cur][j] = min(dp[cur][j], curmin + pref[j] + gap*j);
				// cout << "   " << j << ":  " << pref[j] << 
				// 	" " << dp[cur][j] << "  -  " << curmin << 
				// 	" suf: " << suf[j] << endl;
			}

			curmin = inf;

			//below considers that previous #fixed is at least current fixed
			for (int j = lastsize; j > csize; j--) {
				//consider taking all but this many
				curmin = min(curmin, j * gap + dp[prev][lastsize-j] + 
					suf[j]);
			}
			for (int j = csize; j >= 0; --j) {
				if (lastsize - j >= 0) //j <= lastsize is same 
					curmin = min(curmin, j * gap + dp[prev][lastsize-j] + 
					suf[j]);

				dp[cur][j] = min(dp[cur][j], curmin + pref[j]);
			}




		}

		// cout << cstart << " to " << cend << endl;
		// for (int j = 0; j <= csize; j++) {
				
		// 	cout << "    " <<  j << " : " << dp[cur][j] << endl;
		// }

		// cout << endl;

		lastsize = csize;
		i = cend;
	}

	return dp[cur][lastsize];
}
#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...