一 原题
For long time scientists study the behavior of sharks. Sharks, as many other species, alternate short movements in a certain location and long movements between locations.
Max is a young biologist. For nn days he watched a specific shark, and now he knows the distance the shark traveled in each of the days. All the distances are distinct. Max wants to know now how many locations the shark visited. He assumed there is such an integer kk that if the shark in some day traveled the distance strictly less than kk, then it didn't change the location; otherwise, if in one day the shark traveled the distance greater than or equal to kk; then it was changing a location in that day. Note that it is possible that the shark changed a location for several consecutive days, in each of them the shark traveled the distance at least kk.
The shark never returned to the same location after it has moved from it. Thus, in the sequence of nn days we can find consecutive nonempty segments when the shark traveled the distance less than kk in each of the days: each such segment corresponds to one location. Max wants to choose such kk that the lengths of all such segments are equal.
Find such integer kk, that the number of locations is as large as possible. If there are several such kk, print the smallest one.
The first line contains a single integer nn (1≤n≤1051≤n≤105) — the number of days.
The second line contains nn distinct positive integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109) — the distance traveled in each of the day.
Print a single integer kk, such that
- the shark was in each location the same number of days,
- the number of locations is maximum possible satisfying the first condition,
- kk is smallest possible satisfying the first and second conditions.
8 1 2 7 3 4 8 5 6
7
6 25 1 2 3 14 36
2
In the first example the shark travels inside a location on days 11 and 22 (first location), then on 44-th and 55-th days (second location), then on 77-th and 88-th days (third location). There are three locations in total.
In the second example the shark only moves inside a location on the 22-nd day, so there is only one location.
二 分析
给定一个数组a1,a2,...,an(n<=10^5, ai<=10^9),数组中没有重复的数字。 设定一个值k,把数组中每个大于等于k的数看作一个分割点,这样可以把数组分割成若干段(分割点本身并不属于任何一段)。要求这样的k,使得:(1)每段的长度相同,(2)段数最多,(3)满足前两个条件的情况下,k最小。
首先,k一定比某个ai大1,于是我们可以从小到大枚举每个可能的k值。每次k发生变化,会导致数组中最多有一处(原数组没有重复数字)发生区间合并,可以用并查集实现这一过程。并查集中的根节点表示一段区间的起始坐标,同时记录一下这段区间的长度。用一个全局的set记录当前所存在的区间长度,当set大小为1的时候,就满足了条件1),用一个cnt数组记录特定长度的区间的数量,条件2)就是要最大化这个值。
三 代码
#include <cstdio>
#include <vector>
#include <set>
#include <utility>
#include <algorithm>
// #define local
#define pb push_back
#define fi first
#define se second
typedef std::pair<int, int> pii;
const int maxn = 1e5 + 5;
int n, a[maxn], cnt[maxn], num, ans;
std::vector<pii> v;
std::set<int> s;
struct Dsu {
struct Node {
int val, fa;
} t[maxn];
void init(int sz) {
for (int i = 0; i < n; i++)
t[i].val = 1, t[i].fa = i;
}
int root(int x) {
if (t[x].fa == x) return x;
else return t[x].fa = root(t[x].fa);
}
void unite(int x, int y) {
int fx = root(x);
int fy = root(y);
if (fx > fy) std::swap(fx, fy);
t[fy].fa = fx;
t[fx].val += t[fy].val;
}
int query(int x) {
return t[root(x)].val;
}
} dsu; // call init() before any further operation
int main() {
#ifdef local
freopen("d.in", "r", stdin);
#endif
scanf("%d", &n);
dsu.init(n);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
v.push_back({a[i], i});
}
std::sort(v.begin(), v.end());
for (auto item: v) {
int idx = item.se, k = item.fi + 1, len;
if (idx > 0 && a[idx - 1] < k) {
len = dsu.query(idx - 1);
cnt[len]--;
if (cnt[len] == 0) s.erase(len);
dsu.unite(idx - 1, idx);
}
if (idx < n - 1 && a[idx + 1] < k) {
len = dsu.query(idx + 1);
cnt[len]--;
if (cnt[len] == 0) s.erase(len);
dsu.unite(idx, idx + 1);
}
len = dsu.query(idx);
if (cnt[len] == 0) s.insert(len);
cnt[len]++;
if (s.size() == 1) {
int tmp = cnt[*s.begin()];
if (tmp > num) num = tmp, ans = k;
}
}
printf("%d\n", ans);
return 0;
}