双指针尺取法 2017 Open Cup Ice cream samples
给出n个可重集合,k种
现在让你从这些可重集合中找出一些使得这些集合包含所有的k个数
并且你所选的所有可重集合的大小之和最小。
这n个集合连成了一个环,你只能挑选其中连续的几个
技巧;因为是环,所以复制一遍
然后用双指针扫啊扫,过程中 记录两个值 一个值是真实答案,另一个是当前集合内的数字种类数
#include <iostream>
#include<bits/stdc++.h>
const int inf = 0x3f3f3f3f;
using namespace std;
int cnt[1000056];
vector<int>data[1000056];
int n,k;
int main()
{
while(~scanf("%d%d",&n,&k))
{
for(int i=1;i<=n;i++)
{
data[i].clear();
cnt[i] = 0;
}
cnt[0] = 0;
for(int i=1;i<=n;i++)
{
int num,v;
scanf("%d",&num);
for(int j=1;j<=num;j++)
{
scanf("%d",&v);
data[i].push_back(v);
}
}
int ans = inf;
int qf=1,qb=0;
int tmpk = 0,reak = 0;
while(qf<=2*n)
{
if(qb-qf+1>=n||tmpk==k||qb==2*n)
{
if(tmpk==k)ans= min(ans,reak);
int l = data[qf%n+1].size();
for(int i=0;i<l;i++)
{
int v= data[qf%n+1][i];
--cnt[v];
if(cnt[v]==0)
{
tmpk--;
}
reak--;
}
qf++;
}
else
{
qb++;
int l = data[qb%n+1].size();
for(int i=0;i<l;i++)
{
int v= data[qb%n+1][i];
++cnt[v];
if(cnt[v]==1)
{
tmpk++;
}
reak++;
}
}
}
if(ans==inf)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}