这一题,是简单的取尺法的应用。
题目大概的意思是:一个人复习一本书,这本书的每一页都有一个知识点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; }
北大ACM3320——Jessica's Reading Problem
时间: 2024-11-03 00:15:37