好像没有人用我这个算法,有可能是思路问题。
可以证明 所取的段的开头、结尾是珠子。
证明:
显然,段内有珠子。
那么如果开头、结尾不是珠子,说明开头、结尾到第一个、最后一个珠子之间没有珠子。不是最优解,矛盾。
证毕。
故枚举珠子作为开头,在二分得到每种珠子在开头位置之后的第一个位置(若没有,在此无解),最大者为结尾。最后的最优解为答案。
#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;
}