题目链接:
http://poj.org/problem?id=3320
解题思路:
题目大意:
为了准备考试,Jessica开始读一本很厚的课本。要想通过考试,必须把课本中的所有知识点都掌握。这本书总共有P页,第i本页恰好有一个知识点a[i],(每个知识点都有一个整数编号)。全书中同一个知识点可能会被多次提到,所以她希望通过阅读其中连续的一些页把所有的知识点都覆盖到。给定每页写到的知识点,请求出要阅读的最少页数。
算法思想:
我们假设从某一页s开始阅读,为了覆盖所有的知识点,需要阅读到t。这样的话可以知道如果从s+1开始阅读的话,那么必须阅读到t'>=t页为止。由此这题也可以使用尺取法。
AC代码:
#include <iostream>
#include <cstdio>
#include <map>
#include <set>
using namespace std;
int P;
int a[1000005];
void solve(){
//计算全部知识点的总数
set<int> all;
for(int i = 0; i < P; i++){
all.insert(a[i]);
}
int n = all.size();
//利用尺取法来求解
int s = 0,t = 0,num = 0;
map<int,int> cnt;//知识点->出现次数的映射
int res = P;
while(1){
while(t < P && num < n){
if(cnt[a[t++]]++ == 0){
//出现新的知识点
num++;
}
}
if(num < n)
break;
res = min(res,t-s);
if(--cnt[a[s++]] == 0){
//某个知识点的出现次数为0了
num--;
}
}
printf("%d\n",res);
}
int main(){
while(~scanf("%d",&P)){
for(int i = 0; i < P; i++)
scanf("%d",&a[i]);
solve();
}
return 0;
}