二分解法爆炸求助
查看原帖
二分解法爆炸求助
552387
DeltaCR楼主2024/10/7 15:32

好像没有人用我这个算法,有可能是思路问题。

思路

可以证明 所取的段的开头、结尾是珠子

证明:
显然,段内有珠子。
那么如果开头、结尾不是珠子,说明开头、结尾到第一个、最后一个珠子之间没有珠子。不是最优解,矛盾。
证毕。

故枚举珠子作为开头,在二分得到每种珠子在开头位置之后的第一个位置(若没有,在此无解),最大者为结尾。最后的最优解为答案。

#include <iostream>
#include <vector>
using namespace std;

const int K = 60;
const long long INF = 0x3f3f3f3f3f3f3f3f;
vector<long long> pos[K + 5];

long long lbound(const vector<long long> &a, long long x) // a 中大于等于 x 的最小数. 
{
	int l = 0;
	int r = a.size() - 1;
	while (l < r)
	{
		int mid = l + r >> 1;
		if (a[mid] >= x) r = mid;
		else l = mid + 1;
	}

	return a[l];
}

int main()
{
	int n, k;
	cin >> n >> k;

	for (int i = 1; i <= k; ++i)
	{
		int t;
		cin >> t;
		while (t--)
		{
			int x;
			cin >> x;
			pos[i].push_back(x);
		}

		pos[i].push_back(INF);
	}

	long long ans = INF;
	for (int i = 1; i <= k; ++i)
	{
		long long res = 0;
		for (int j = 0; j < pos[i].size(); ++j)
		{
			long long p = pos[i][j];
			for (int t = 1; t <= k; ++t) res = max(res, lbound(pos[t], p) - p);
		}

		ans = min(ans, res);
	}

	cout << ans << endl;

	return 0;
}

评测结果

2024/10/7 15:32
加载中...