题目大意:Jessica期末考试临时抱佛脚想读一本书把知识点掌握,但是知识点很多,而且很多都是重复的,她想读最少的连续的页数把知识点全部掌握(知识点都在书上,每一页都是一个知识点)
这一题可以用3061的游标卡尺法,我们可以先数数书上倒到底有多少个知识点,因为知识点都是序数,我们可以用二分法直接找到O(PlogP),这里可以采用set模板直接偷懒了,然后我们就可以用游标卡尺法了,因为所有知识点都要出现一次,所以我们统计新的知识点的出现就好了,最后我们找最短的那个连续就好。
1 #include <iostream> 2 #include <functional> 3 #include <algorithm> 4 #include <map> 5 #include <set> 6 7 using namespace std; 8 9 static int books[1000001]; 10 11 void solve(const int); 12 13 int main(void) 14 { 15 int pages; 16 while (~scanf("%d", &pages)) 17 { 18 for (int i = 0; i < pages; i++) 19 scanf("%d", &books[i]); 20 solve(pages); 21 } 22 return 0; 23 } 24 25 void solve(const int pages) 26 { 27 int ideas_size, s = 0, t = 0, ans, nums = 0;//游标卡尺法标准形式 28 static set<int>ideas; 29 static map<int, int>index;//把ideas和index放函数里面初始化能省几十ms 30 31 for (int i = 0; i < pages; i++) 32 ideas.insert(books[i]); 33 ideas_size = ideas.size(); 34 ans = pages;//ans千万不要初始化成答案个数了,之前在这里初始化错了导致wa 35 36 while (1) 37 { 38 while (t < pages && nums < ideas_size) 39 { 40 if (index[books[t++]]++ == 0)//找不到这个元素,则一定在尾端 41 nums++; 42 } 43 if (nums < ideas_size)//因为知识点的个数一定是符合条件的,所以这里直接作为跳出条件就可以了 44 break; 45 ans = min(ans, t - s); 46 if (--index[books[s++]] == 0) 47 nums--; 48 } 49 printf("%d ", ans); 50 }
因为使用模板的,所以速度会慢一点