DestinHistoire

 

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编辑  收藏  举报

导航