Submission #1129328

#TimeUsernameProblemLanguageResultExecution timeMemory
1129328GervidRabbit Carrot (LMIO19_triusis)C++20
100 / 100
924 ms18356 KiB
#include <iostream>
#include <vector>
#include <set>
#include <limits.h>
#include <random>
#include <array>
#include <fstream>

using namespace std;

mt19937 r, t;

struct Treap
{
	int prio, dpdata, height, size, dpmin;
	array<Treap*, 2> kids;
	Treap(int _dpdata, int _height)
	{
		height = _height;
		dpdata = _dpdata;
		prio = r();
		size = 1;
		dpmin = dpdata;
		kids = { NULL, NULL };
	}
};

int getsize(Treap* treap)
{
	return treap != NULL ? treap->size : 0;
}

int getdpmin(Treap* treap)
{
	return treap != NULL ? treap->dpmin : INT_MAX;
}

void recalc(Treap* me)
{
	me->dpmin = min(me->dpdata, min(getdpmin(me->kids[0]), getdpmin(me->kids[1])));
	me->size = 1 + getsize(me->kids[0]) + getsize(me->kids[1]);
}

array<Treap*, 2> split(Treap* me, int x)
{
	if (me == NULL) return { NULL, NULL };

	if (x <= getsize(me->kids[0]))
	{
		array<Treap*, 2> res = split(me->kids[0], x);
		me->kids[0] = res[1];
		recalc(me);
		return { res[0], me };
	}
	else
	{
		array<Treap*, 2>res = split(me->kids[1], x - getsize(me->kids[0]) - 1);
		me->kids[1] = res[0];
		recalc(me);
		return { me, res[1] };
	}
}

Treap* merge(Treap* left, Treap* right)
{
	if (left == NULL) return right;
	if (right == NULL) return left;

	if (left->prio < right->prio)
	{
		left->kids[1] = merge(left->kids[1], right);
		recalc(left);
		return left;
	}
	else
	{
		right->kids[0] = merge(left, right->kids[0]);
		recalc(right);
		return right;
	}
}

//int findidx(int x, Treap* treap, int index = -1)
//{
//	if (index == -1) index = getsize(treap->kids[0]);
//
//	if (treap->height == x && (treap->kids[1] == NULL || treap->kids[1]->height != x)) return index;
//	if (treap->height <= x)
//	{
//		if (treap->kids[1] == NULL) return index;
//		return findidx(x, treap->kids[1], index + getsize(treap->kids[1]->kids[0]) + 1);
//	}
//	else
//	{
//		if (treap->kids[0] == NULL) return index;
//		return findidx(x, treap->kids[0], index - getsize(treap->kids[0]->kids[1]) - 1);
// 	}
//}

int getvalue(int idx, Treap* treap, int current = -1)
{
	if (current == -1) current = getsize(treap->kids[0]);
	if (idx < current) return getvalue(idx, treap->kids[0], current - getsize(treap->kids[0]->kids[1]) - 1);
	if (idx > current) return getvalue(idx, treap->kids[1], current + getsize(treap->kids[1]->kids[0]) + 1);
	return treap->height;
}

int bsidx(int x, Treap* treap)
{
	int l = 0, r = getsize(treap), m;
	while (l + 1 < r)
	{
		m = (l + r) / 2;
		if (getvalue(m, treap) <= x) l = m;
		else r = m;
	}
	return l;
}

int popcnt(int x)
{
	int ans = 0;
	while (x > 0)
	{
		ans += x & 1;
		x >>= 1;
	}
	return ans;
}
int BruteForce(int n, int m, vector<int> a)
{
	int i, minv = INT_MAX;
	for (int mask = 0; mask < (1<<n); mask++)
	{
		int h = 0, pc = popcnt(mask);
		if (pc >= minv) continue;
		for (i = 0; i < n; i++)
		{
			h += m;
			if (!((mask >> i) & 1))
			{
				if (h < a[i+1]) break;
				h = a[i + 1];
			}
		}
		if (i == n) minv = min(minv, pc);
	}
	return minv;
}

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


	int n, m, i;
	cin >> n >> m;

	vector<int> a(n+1);
	for (i = 1; i <= n; i++) cin >> a[i];
	a[0] = 0;

//start:
//	n = 1 + r() % 10, m = r() % 10;
//	a.resize(n + 1);
//	for (i = 1; i <= n; i++) a[i] = r() % 10;

	{
		vector<Treap> storage = { Treap(n + 1, -1) }; //dp value is always offset by i
		storage.reserve(n + 2);

		Treap* treap = &storage[storage.size() - 1];

		multiset<int> heights = { -1 };

		int dis = 0, dpmin = 0, index, smaller_height;
		for (i = n; i >= 0; i--)
		{
			set<int>::iterator it = prev(heights.upper_bound(a[i] + dis));
			smaller_height = *it;
			index = bsidx(smaller_height, treap);

			array<Treap*, 2> parts = split(treap, index + 1);
			dpmin = parts[0]->dpmin - i - 1;

			storage.push_back(Treap(dpmin + i, a[i] + dis));
			treap = merge(parts[0], merge(&storage[storage.size() - 1], parts[1]));
			heights.insert(a[i] + dis);
			dis += m;
		}
		cout << dpmin << '\n';

		//if (BruteForce(n, m, a) == dpmin) goto start;
		//else
		//{
		//	cout << BruteForce(n, m, a) << '\n';
		//	cout << n << ' ' << m << '\n';
		//	for (i = 1; i < n + 1; i++) cout << a[i] << ' ';
		//}
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...