poj 3320 Jessica's Reading Problem

这道题的题意是求能够把全部知识点都覆盖的最小页数,就比如:

1 2 2 2 1

只需要读前两页就能读完所有知识点,因此答案即为2.

那么对于这道题的做法来说,需要选择hash表跟尺取法。

我们以以下数列为例:

12 13 15 17 13 12 15 12 17 15

每一次先寻找到一个能够覆盖所有知识点的区间[s,t](t<=书页总数目),然后把开头s去掉,如果此时开头s这个知识点的出现次数为0的话,就要把区间内知识点的总数-1.

接着在寻找一个能够覆盖所有知识点的区间[s+1,t'](t'<=书页总数目),然后把开头s+1去掉,如果此时开头s+1这个知识点的出现次数也为0的话,就把区间内知识点的总数-1。以此不断的推进t跟s,每一次新加页出现某知识点的话,就要把该知识点出现的次数加1.

于是,对于每一次寻找的数列为:

12 13 15 17

     13 15 17 13 12

          15 17 13 12

               17 13 12 15

                    13 12 15 12 17

                         12 15 12 17 15 

另外,输入输出记得用cin,cout会超时。

#include <cstdio>
#include <map>
#include <set>
int a[1000004];
using namespace std;
int main()
{
	int n;
	while (~scanf("%d",&n))
	{
		set<int> t_set;
		map<int, int> t_map;
		for (int i = 0; i < n; i++)
		{
			scanf("%d",&a[i]);
			t_set.insert(a[i]);
		}
		int cnt = t_set.size();
		int left = 0;
		int right = 0;
		int num = 0;
		int res = n;
		while (true)
		{
			while (right < n&&num < cnt)
			{
				if (!t_map[a[right]])
				{
					num++;
				}
				t_map[a[right]]++;
				right++;
			}
			if (num < cnt)
				break;
			res = res < right - left ? res : right - left;
			t_map[a[left]]--;
			if (!t_map[a[left]])
				num--;
			left++;
		}
		printf("%d\n",res);
	}
	return 0;
}


你可能感兴趣的:(hash表,尺取法)