CTU OPEN 2017 Ice cream samples /// 尺取法
题目大意:
给定n k
接下来n行 给定n个摊位的冰淇淋信息
首先给一个t 表示这个摊位有t个冰淇淋 接下来t个数表示对应冰淇淋的品种
走到连续的几个摊位 会买下走过的摊位的所有的冰淇淋
求 要买下所有k个品种的冰淇淋 最少需要买下多少冰淇淋
尺取法
L R指针移动 表示走过L~R的摊位
利用cnt[]记录品种信息
#include <bits/stdc++.h> using namespace std; #define LL long long #define INF 0x3f3f3f3f #define mem(i,j) memset(i,j,sizeof(i)) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) #define gcd(i,j) __gcd(i,j); const int N=1e6+5; const int mod=1e9+7; const double eps=1e-8; int n,k; vector<int>v[N]; // v[i]中存有i摊位有的品种 int cnt[N]; // cnt[i]为此时区间中i品种的数量 int main() { while(~scanf("%d%d",&n,&k)) { inc(i,1,n) v[i].clear(); inc(i,1,k) cnt[i]=0; inc(i,1,n) { int t; scanf("%d",&t); while(t--) { int m; scanf("%d",&m); v[i].push_back(m); } } int ans=INF; int L=1,R=1,num=0,all=0; while(L<=n) { int len=v[R].size(); all+=len; inc(i,0,len-1) // 记录这个摊位的品种 if(cnt[v[R][i]]++==0) num++; R= (R+1)%n==0 ? n:(R+1)%n; if(R==L && num<k) break; // 说明所有摊位都无法凑齐所有品种 while(num==k && L<=n) { // 找到了k个品种 ans=min(ans,all); len=v[L].size(); inc(i,0,len-1) // 移动左端 可能有富余 if(--cnt[v[L][i]]==0) num--; L++; all-=len; } } if(ans==INF) printf("-1\n"); else printf("%d\n",ans); } return 0; }