poj 3320 尺取法

链接:http://poj.org/problem?id=3320
还是运用尺取法的思路。
思路:
将头往前走,如果这个知识点没有出现过,将已有的知识点数量+1。如果覆盖了所有知识点,更新当前的最少页数。此时在判断尾巴出现的知识点是否出现超过一次,如果超过一次,那么就将尾巴往前移。因为如果没有超过一次也往前移的话,那么知识点就会少一个,导致之后头要往前移才有可能再次覆盖所有知识点,才可能再次更新。所以这其实并不一定要这样做,只有出现知识点重复的时候再将尾巴向前移动就可以。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
using namespace std;
#define M 1000000
#define INF 0x3f3f3f3f
int a[M];
int main()
{
    int n;
    while(scanf("%d",&n)==1)
    {
        map<int,int> mp;
        set<int> s;
        for(int i = 0;i < n;i++)
        {
            scanf("%d",&a[i]);
            s.insert(a[i]);
            mp[a[i]]++;
        }
        int total = s.size();
        int st = 0, en = 0;
        int ans = INF;
        map<int,int> mp1;
        int num = 0;
        for(en = 0;en < n;en++)
        {
            if(mp1[a[en]] == 0)
                num++;
            mp1[a[en]]++;
            while(num == total)
            {
                ans = min(ans,en-st+1);
                if(mp1[a[st]]>1)
                {
                    mp1[a[st]]--;
                    st++;  //如果该知识点出现超过1次,将尾巴移动一个
                }
                else break;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(poj 3320 尺取法)