POJ 3320 Jessica's Reading Problem 尺取法 map运用

本文介绍了一种使用滑动窗口解决最短连续子数组覆盖所有知识点的问题。通过构造<int,int>映射,记录知识点出现次数,实现了高效算法。关键在于利用map的特性,初始化未出现的知识点计数为0。

Description

Jessica's a very lovely girl wooed by lots of boys. Recently she has a problem. The final exam is coming, yet she has spent little time on it. If she wants to pass it, she has to master all ideas included in a very thick text book. The author of that text book, like other authors, is extremely fussy about the ideas, thus some ideas are covered more than once. Jessica think if she managed to read each idea at least once, she can pass the exam. She decides to read only one contiguous part of the book which contains all ideas covered by the entire book. And of course, the sub-book should be as thin as possible.

A very hard-working boy had manually indexed for her each page of Jessica's text-book with what idea each page is about and thus made a big progress for his courtship. Here you come in to save your skin: given the index, help Jessica decide which contiguous part she should read. For convenience, each idea has been coded with an ID, which is a non-negative integer.

Input

The first line of input is an integer P (1 ≤ P ≤ 1000000), which is the number of pages of Jessica's text-book. The second line contains P non-negative integers describing what idea each page is about. The first integer is what the first page is about, the second integer is what the second page is about, and so on. You may assume all integers that appear can fit well in the signed 32-bit integer type.

Output

Output one line: the number of pages of the shortest contiguous part of the book which contains all ideals covered in the book.

Sample Input

5
1 8 8 8 1

Sample Output

2


题意比较好理解,就不多说了。基本方法就是尺取法,否则数据太大过不了。关键是“每个知识点都复习到”这个需求如何实现。
我一开始想的是set存出现的元素,map则将每个元素与一个偏移量一一对应。但是,看了网上的博客,才发现有更好的方法。那就是,构造<int,int>的map,用map【key】来存放每个键值出现的次数。这里用到了一个非常重要的性质:在创建一个新的key的时候,它的value会被初始化为0(因为是int)。所以直接map【key】++,就可以构成算法的核心部分。另外,尺取法的左指针在右移前,对应的也要将其value减一,并且(重要!!!!)如果这个时候value<=0,就要删除这个键值。为啥?想一想我们在尺取法中是如何判断右指针到达指定位置了?是不是要此刻左指针与右指针之间恰好有全部知识点?我们可以用map的size()函数来表示有多少知识点,而当value<=0时,该知识点就不存在了,所以要删掉。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<climits>
#include<cmath>
#include<string>
#include<sstream>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
int a[1000000+10],p,temp,l,r,n;
map<int,int> beifen,x;
int main(void)
{
    int ans;
    cin>>p;
    for(int i=1;i<=p;i++)
    {
        scanf("%d",&temp);
        a[i]=temp;
        beifen[temp]++;//important! when the key 'temp' does not exist,then a new key 'temp'is created when its value is initialized to 0
    }
    l=1;
    r=1;
    ans=INT_MAX;
    //x[a[1]]++;
    n=beifen.size();
    while(1)
    {
        while((r<=p)&&(x.size()<n))
        {
            x[a[r++]]++;
        }
        if(x.size()<n)
            break;
        ans=min(ans,r-l);
        l++;
        x[a[l-1]]--;
        if(x[a[l-1]]<=0)
            x.erase(a[l-1]);

    }
    cout<<ans<<endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值