这一题,是简单的取尺法的应用。
题目大概的意思是:一个人复习一本书,这本书的每一页都有一个知识点ai,每一页的知识点可能会与其他页的知识点相同,问你如何读最少页,将所以知识点读完。
使用STL中的 set 来判断里面有多少个不同的知识点num, 用STL中的 map 表示知识点与出现次数的映射。
同样的设置知识点数sum,页数的起点和终点s和t。首先将知识点的数组a 加入map中,直到sum >= num,更新需要看多少页,去掉开头那一页,判断知识点是否少了,少了,则 t 再自增,继续加入,否则,再去掉开头那页。不断循环,更新需要看的最少页数。
下面是AC代码:
- #include <iostream>
- #include <cstdio>
- #include <map>
- #include <set>
- using namespace std;
-
- int n;
- int a[1000005];
-
- int min(int x, int y)
- {
- return x > y ? y : x;
- }
-
- void solve()
- {
- set<int>count;
- for(int i = 0; i < n; i++) //数有几个不同的知识点
- count.insert(a[i]);
- int num = count.size();
- map<int, int>finds; //知识点与出现次数的映射
- int s, t, sum;
- s = t = sum = 0; //起始页与末尾页,知识点数的初始化
- int res = n;
- while(1)
- {
- while(t < n && sum < num)
- if(finds[a[t++]]++ == 0) //出现新的知识点
- sum++; //增加知识点数
- if(sum < num) //知识点数少于总的,则可以退出循环了,到尽头了
- break;
- res = min(res, t - s); //计算页数
- if(--finds[a[s++]] == 0) //去掉起始页,判去掉该知识点,该知识点的次数是否为0,是,则知识点数 - 1
- sum--;
- }
- printf("%d\n", res);
- }
-
- int main()
- {
- scanf("%d", &n);
- for(int i = 0; i < n; i++)
- scanf("%d", &a[i]);
- solve();
- return 0;
- }