【题目链接】
【思路要点】
- 对于一个左端点\(i\),设最小的合法右端点为\(F_i\)。
- 显然,\(F_i\)是单调不减的,用Two Pointers计算可能的\(F_i\)即可。
- 时间复杂度\(O(NLogN)\)。
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 1000005 #define INF 2100000000 #define MAXK 105 struct info {int pos, type; }; info a[MAXN]; bool cmp(info x, info y) {return x.pos<y.pos; } int main() { int n, k; scanf("%d%d", &n, &k); int tot = 0; for (int i = 1; i <= k; i++) { int sum; scanf("%d", &sum); for (int j = 1; j <= sum; j++) { int tmp; scanf("%d", &tmp); a[++tot] = (info){tmp, i}; } } sort(a+1, a+n+1, cmp); int now = 1, cnt = 0, ans = INF; static int mark[MAXK]; for (int i = 1; i <= n; i++) { while (now <= n && cnt<k) { if (mark[a[now].type] == 0) cnt++; mark[a[now].type]++; now++; } if (cnt == k) ans = min(ans, a[now-1].pos-a[i].pos); if (mark[a[i].type] == 1) cnt--; mark[a[i].type]--; } printf("%d\n", ans); return 0; }