#1572 小Hi与花盆
Time Limit:10000ms
Case Time Limit:1000ms
Memory Limit:256MB
Description
小Hi家的阳台上摆着一排N个空花盆,编号1~N。从第一天开始,小Hi每天会选择其中一个还空着花盆,栽种一株月季花,直到N个花盆都栽种满月季。
我们知道小Hi每天选择的花盆的编号依次是A1, A2, ... AN。随着花盆中被栽种上月季,连续的空花盆数量越来越少。
现在小Ho想知道,第一次出现恰好K个连续空花盆(恰好是指这K个空花盆两边相邻的位置都不是空花盆)是第几天?
假设N=7,K=2,小Hi第1天~第7天选择的花盆编号依次是:4、2、7、5、1、3、6。
1234567 OOOOOOO 第0天,一段7个连续空花盆 OOOXOOO 第1天,一段3个连续空花盆,和另一段3连续个空花盆 OXOXOOO 第2天,1个、1个和3个连续空花盆 OXOXOOX 第3天,第一次出现2个连续空花盆 ....
Input
第一行包含两个整数,N和K。
第二行包含N个两两不同的整数,A1, A2, ... AN。
对于30%的数据, 1 <= K < N <= 1000
对于100%的数据,1 <= K < N <= 100000, 1 <= Ai <= N
Output
输出第一次出现恰好连续K个空花盆是第几天。如果自始至终没出现输出-1。
- Sample Input
-
7 2 4 2 7 5 1 3 6
- Sample Output
-
3
思路:每次在一个空花盆种植,会将原先的一个连续空花盆分裂成两个连续空花盆,所以每次选择一个空花盆编号,只要计算这个空花盆编号及与其最近的两个编号的连续空花盆数,将产生的两个值与K进行比较。所以需要降低查找的复杂度,可以用set(会默认按照升序排列好)。
C++代码:
1 #include <iostream> 2 #include <set> 3 using namespace std; 4 5 int main() { 6 int N, K, id; 7 cin >> N >> K; 8 set<int> st; 9 int ans = -1; 10 st.insert(0); st.insert(N + 1); 11 bool finded = false; 12 for (int i = 1; i <= N; ++i) { 13 scanf("%d", &id); 14 if (finded) continue; 15 auto it = st.upper_bound(id); 16 int right = *it, left = *(--it); 17 if ((id - 1 - left == K) || (right - 1 - id == K)) { 18 finded = true; 19 ans = i; 20 } 21 st.insert(id); 22 } 23 printf("%d\n", ans); 24 return 0; 25 }
越努力,越幸运