CF982D Shark
Posted 王宜鸣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF982D Shark相关的知识,希望对你有一定的参考价值。
思路:
给定k之后,求解的过程其实类似于一个“分段”的过程,即把所有大于等于k的数去掉,判断剩下的若干段是否满足条件。这样扫描一次是O(n)的,如果对所有的k都这样做一次,那么复杂度很高(O(n2))。所以需要优化,使得对于每个k不必O(n)。具体来说,我们使用set动态模拟“分段”的过程,set中存放的若干个“段”的起点和终点(初始时只有一个段(1,n))。首先将a数组按照从大到小排序,然后从前到后遍历数组,从set中找到当前数字所在的段,并根据数字所在位置将此段一分为二,判断此时是否满足条件并更新最优答案,直至结束。判断是否满足条件的方法是用map动态维护不同长度的段的个数,若这些段的长度种类只有一种就是可以的。算法的时间复杂度大约是O(n * log(n))。
实现:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int MAXN = 100005; 5 const int INF = 0x3f3f3f3f; 6 7 typedef pair<int, int> pii; 8 9 pii a[MAXN]; 10 11 int main() 12 { 13 int n; 14 while (cin >> n) 15 { 16 for (int i = 1; i <= n; i++) { cin >> a[i].first; a[i].second = i; } 17 sort(a + 1, a + n + 1); 18 set<pii> st; st.insert(pii(1, n)); 19 map<int, int> mp; mp[n] = 1; 20 int maxn = 0, ans = -1; 21 for (int i = n; i >= 1; i--) 22 { 23 if ((int)mp.size() == 1 && mp.begin()->second >= maxn) 24 { 25 maxn = mp.begin()->second; ans = a[i].first + 1; 26 } 27 auto it = st.upper_bound(pii(a[i].second, INF)); 28 it--; 29 if (it->first <= a[i].second - 1) 30 { 31 pii x(it->first, a[i].second - 1); 32 st.insert(x); 33 mp[x.second - x.first + 1]++; 34 } 35 if (a[i].second + 1 <= it->second) 36 { 37 pii y(a[i].second + 1, it->second); 38 st.insert(y); 39 mp[y.second - y.first + 1]++; 40 } 41 int l = it->second - it->first + 1; 42 st.erase(it); 43 mp[l]--; if (!mp[l]) mp.erase(l); 44 } 45 cout << ans << endl; 46 } 47 return 0; 48 }
以上是关于CF982D Shark的主要内容,如果未能解决你的问题,请参考以下文章