题意是一个妹子要复习了,然后一本书上每一页是一个知识点,问你最少连续看多少页可以看完全部的知识点。
这个题的做法是尺取法,我们需要检测已有的序列(low~up)中出现的知识点的总数,和书本实际的知识点的总数进行比较就可以知道是否覆盖全部的知识点了。这个题用了set来记录知识点的总个数(这是个黑科技,set中相同的信息只会记录一次,所以set的size就是知识点的总个数) 我们用map来记录已有的序列(low~up)里每个知识点出现的次数。
#include<stdio.h>
#include<iostream>
#include<map>
#include<set>
using namespace std;
const int maxn=1e6+10;
int page[maxn];
int main()
{
int n,minn,low,up,sum,now;
set<int>all;
all.clear();
map<int,int>icount;
icount.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&(page[i])),all.insert(page[i]);
minn=n;
low=1;
sum=all.size();
now=0;
for(int up=1;up<=n;up++)
{
if(icount[page[up]]==0)
now++;
icount[page[up]]++;
if(now==sum)//up往右走了之后,满足获得的总知识数等于书本的总知识数时,要更新minn
minn=min(minn,up-low+1);
while(low<up&&now==sum)//在保证low右移后不大于up的前提下,如果满足了满足获得的总知识数等于书本的总知识数,就开始右移,直到low==up或者是now<sum时推出low右移,然后up开始右移,直到满足条件之后,low又开始右移,就这样周而复始就可以把每个满足条件(now==sum)的区间都遍历到了
{
if(icount[page[low]]==1)
now--;
icount[page[low]]--;
low++;
if(now==sum)//如果low往右走了之后,仍然满足获得的总知识数等于书本的总知识数时,也要更新minn,因为now==sum说明这次的low右移除去了"冗余"的知识点,那序列长度肯定是变小了。我就因为漏了这个更新wa了一发
minn=min(minn,up-low+1);
}
}
printf("%d\n",minn);
return 0;
}