BZOJ-1293 [SCOI2009]生日礼物(尺取法)
题目描述
彩珠有 \(1\leq n\leq 10^6\) 个,分为 \(1\leq k\leq 60\) 种。可以将彩带考虑为 \(x\) 轴,每一个彩珠有一个对应的坐标(即位置)。某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上。剪一段彩带,能包含所有种类的彩珠,同时使彩带尽可能短,求最短的长度。
分析
记录每个彩珠的颜色和位置,按位置从小到大排序,尺取法,右指针右移的时候记录颜色 \(i\) 出现了 \(tot[i]\) 次,记录当前不同颜色数 \(sum\),\(sum=k\) 时左指针右移,删去对应颜色出现的次数和不同颜色数。
代码
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int N=1e6+10;
const int INF=0x3f3f3f3f;
struct node
{
int pos;
int ID;
}a[N],temp[N];
int tot[N];
bool cmp(node A,node B)
{
return A.pos<B.pos;
}
int main()
{
int n,k,cnt=0;
cin>>n>>k;
for(int i=1;i<=k;i++)
{
int x=read();
for(int j=1;j<=x;j++)
{
cnt++;
a[cnt].pos=read();
a[cnt].ID=i;
}
}
sort(a+1,a+1+cnt,cmp);
int ans=INF;
int l=1,r=0,sum=0;
for(int i=1;i<=n;i++)
{
r++;
temp[r].pos=a[i].pos;
temp[r].ID=a[i].ID;
tot[a[i].ID]++;
if(tot[a[i].ID]==1)
sum++;
while(sum==k)
{
ans=min(ans,temp[r].pos-temp[l].pos);
tot[temp[l].ID]--;
if(tot[temp[l].ID]==0)
sum--;
l++;
}
}
cout<<ans<<endl;
return 0;
}
posted on 2020-12-11 20:21 DestinHistoire 阅读(51) 评论(0) 编辑 收藏 举报