BZOJ1293&&洛谷P2564[SCOI2009]生日礼物

单调队列

貌似是这个

我们按照位置排序后,将每个位置依次加到队列里,然后判断是不是最早出现的点到这个点之间有所有种类的珠子,有的话向右移动左端点,不断更新答案,直到珠子种类少于总数为止

代码

//By AcerMo
#include
#include
#include
#include
#include
using namespace std;
const int M=1000500;
struct poi
{
	int p,id;
	bool friend operator < (poi x,poi y)
	{return x.p<y.p;}
}e[M];
int n,m,cnt;
int q[M],tot[M],tp,tl=1;
inline void read(int &x)
{
	x=0;char ch=getchar();
	while (!isdigit(ch)) ch=getchar();
	while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
	return ;
}
signed main()
{
	read(n);read(m);int x;
	for (int i=1;i<=m;i++)
	{
		read(x);
		while (x--)
		read(e[++cnt].p),e[cnt].id=i;
	}
	sort(e+1,e+n+1);int mi=2e9,s=0;
	for (int i=1;i<=n;i++)
	{
		tot[e[i].id]++;q[++tp]=i;
		if (tot[e[i].id]==1) s++;
		while (s==m)
		{
			int u=q[tp],v=q[tl++];
			mi=min(mi,e[u].p-e[v].p);
			if (--tot[e[v].id]==0) s--;
		}
	}
	cout<<mi;
	return 0;
}

你可能感兴趣的:(数据结构-堆)