[SCOI2009]生日礼物
思路
如果没有记错的话,这题跟某次多校的题几乎一模一样。
区间问题的最小值,有一个最简单的办法就是尺取法了,只要通过两个指针的扫描就可以以线性的复杂度简单的实现,这里我们按照每个物品属于的种类作为我们num数组记录的值,然后再通过一次扫描就可以得到答案了。
代码
/* Author : lifehappy */ #pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> #define mp make_pair #define pb push_back #define endl '\n' #define mid (l + r >> 1) #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r #define ls rt << 1 #define rs rt << 1 | 1 using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const double pi = acos(-1.0); const double eps = 1e-7; const int inf = 0x3f3f3f3f; inline ll read() { ll f = 1, x = 0; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } return f * x; } const int N = 1e6 + 10; struct Node { int pos, id; bool operator < (const Node & t) const { return pos < t.pos; } }a[N]; int num[N], n, k; int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); n = read(), k = read(); int tot = 0; for(int i = 1; i <= k; i++) { int x = read(); for(int j = 1; j <= x; j++) { int t = read(); tot++; a[tot].id = i; a[tot].pos = t; } } sort(a + 1, a + 1 + tot); int ans = inf, l = 1, r = 1, cnt = 0; for(;;) { while(r <= tot && cnt < k) { cnt += !num[a[r++].id]++; } if(cnt < k) break; ans = min(ans, a[r - 1].pos - a[l].pos); cnt -= !(--num[a[l++].id]); } cout << ans << endl; return 0; }