Submission #20621

#TimeUsernameProblemLanguageResultExecution timeMemory
20621model_codeShortcut (IOI16_shortcut)C11
100 / 100
1399 ms40184 KiB
// name = shortcut_c.c, type = c.gcc

#include "shortcut_c.h"
#include <stdio.h>
#include <stdlib.h>

typedef long long ll;
typedef struct llpair {
	ll fi;
	ll se;
} llpair;

#define maxn 1000005
const ll inf = 1e18;

ll x[maxn], d[maxn];
int n, C;
llpair q[maxn];
int ans1, ans2;

llpair mp(ll fi, ll se) {
	llpair res;
	res.fi = fi;
	res.se = se;
	return res;
}

ll min(ll a, ll b) {
	return a < b ? a : b;
}

ll max(ll a, ll b) {
	return a > b ? a : b;
}

ll max3(ll a, ll b, ll c) {
	return max(max(a, b), c);
}

int can(ll diam)
{
// 	cout << "can " << diam << endl;
	int needleft = 0;
	ll maxsum = inf;
	ll minsum = -inf;
	ll maxdif = inf;
	ll mindif = -inf;
	llpair mostleft;
	mostleft.fi = inf;
	mostleft.se = -inf;
	llpair mostright;
	mostright.fi = -inf;
	mostright.se = -inf;
	int l = 0;
	int r = 0;
	for (int i = 0; i < n; i++)
	{
		// no need to check whether it is "small" or not, because in case of "small" its square is inside "big"'s square
		while (r > l && x[i] - q[l].fi + d[i] > diam)
		{
			int wh = q[l].se;
			l++;
			if (x[wh] - d[wh] < mostleft.fi - mostleft.se) mostleft = mp(x[wh], d[wh]);
			if (x[wh] + d[wh] > mostright.fi + mostright.se) mostright = mp(x[wh], d[wh]);
			needleft = 1;
		}
		if (needleft)
		{
			maxsum = min(maxsum, (mostleft.fi + diam - C - d[i] - mostleft.se) + x[i]);
			minsum = max(minsum, (mostright.fi - (diam - C - d[i] - mostright.se)) + x[i]);
			maxdif = min(maxdif, x[i] - (mostright.fi - (diam - C - d[i] - mostright.se)));
			mindif = max(mindif, x[i] - (mostleft.fi + diam - C - d[i] - mostleft.se));
		}
		while (r > l && q[r - 1].fi > x[i] - d[i]) r--;
		q[r++] = mp(x[i] - d[i], i);
	}
// 	cout << minsum << ' ' << maxsum << ' ' << mindif << ' ' << maxdif << endl;
	if (maxsum < minsum || maxdif < mindif) return 0;
	int curdif = 0;
	int cursum = n;
	for (int i = 0; i < n; i++)
	{
		while (curdif < n && x[curdif] - x[i] < mindif) curdif++;
		while (cursum > 0 && x[cursum - 1] + x[i] >= minsum) cursum--;
		int cur = max3(cursum, curdif, i + 1);
		if (cur < n && x[cur] + x[i] <= maxsum && x[cur] - x[i] <= maxdif)
		{
			ans1 = i;
			ans2 = cur;
			return 1;
		}
	}
	return 0;
}

long long find_shortcut(int N, int* L0, int* L, int C_)
{
	n = N;
	C = C_;
	ll cursum = 0;
	for (int i = 0; i < n; i++)
	{
		d[i] = L[i];
		x[i] = cursum;
		if (i + 1 < n) cursum += L0[i];
	}
	ll l = 0;
	ll r = inf;
	while (r - l > 1)
	{
		ll mid = (l + r) / 2;
		if (can(mid)) r = mid;
		else l = mid;
	}
	can(r);
	return r;
}


#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...