1. 程式人生 > 實用技巧 >P2564 [SCOI2009]生日禮物

P2564 [SCOI2009]生日禮物

題意

  • 尋找最小的區間使得它包含全部的\(k\)個元素

\(set\)存下每個顏色最後的出現點,直接求出最大值即可

#include<bits/stdc++.h>
#define For(i, a, b) for(int i = (a), en = (b); i <= en; ++i)
#define Rof(i, a, b) for(int i = (a), en = (b); i >= en; --i)
#define Tra(u, i) for(int i = hd[u]; ~i; i = e[i].net)
#define cst const
#define LL long long
#define DD double
#define LD long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define inf 0x3f3f3f3f
#define Inf 0x3f3f3f3f3f3f3f3f
#define eps 1e-12
#define maxn 1000000
using namespace std;

int n, k, b[maxn + 5], cnt = 0, as = inf;
vector<int> vec[maxn + 5], T[maxn + 5];

template <class T>
void read(T &x){
	char ch;
	bool ok;
	for(ok = 0, ch = getchar(); !isdigit(ch); ch = getchar()) if(ch == '-') ok = 1;
	for(x = 0; isdigit(ch); x = x * 10 + ch - '0', ch = getchar());
	if(ok) x = -x;
}

int find(int x){return lower_bound(b + 1, b + cnt + 1, x) - b;}

int to[maxn + 5];
set<pair<int, int> > se;
int main(){
	//freopen("gift.in", "r", stdin);
	//freopen("gift.out", "w", stdout);
	read(n); read(k);
	For(i, 1, k){
		int t; read(t);
		For(j, 1, t){
			int x; read(x);
			T[i].pb(x);
			b[++cnt] = x;
		}
	}
	sort(b + 1, b + cnt + 1);
	cnt = unique(b + 1, b + cnt + 1) - b - 1;
	For(i, 1, k) for(auto j : T[i]) vec[find(j)].pb(i);
	For(i, 1, cnt){
		for(auto j : vec[i]){
			se.erase(mp(to[j], j));
			se.insert(mp(to[j] = i, j));
		}
		if(se.size() == k) as = min(as, b[i] - b[se.begin()->fir]);
	}
	printf("%d\n", as);
	return 0;
}