Blog of RuSun

\begin {array}{c} \mathfrak {One Problem Is Difficult} \\\\ \mathfrak {Because You Don't Know} \\\\ \mathfrak {Why It Is Diffucult} \end {array}

AGC006D Median Pyramid Hard

LuoGu: AT2165 [AGC006D] Median Pyramid Hard

AtCoder: D - Median Pyramid Hard

考虑将序列转化一个 01 序列,设最上方的数为 $k$ ,其中 $0$ 表示 $ > k$ ,$1$ 表示 $\le k$ ,考虑这个序列变化的过程,注意到如果有两个数相同,那么这两个数将不变知道序列的这个位置消失。我们找到距离中点最近的位置,使得相邻两个数相同,那么距离中点更近的位置都是 01 交替的,在相同的数的位置消失后,便会影响交替的部分,直至最高点;如果没有这个相邻两个数相同,注意到长度一定为奇数,那么更多的会影响结果。如果最上方不是 $0$ ,即为矛盾。我们要求最小的 $k$ ,单调性是显然的,二分这个 $k$ 即可。

查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <cstdio>
using namespace std;
template <class Type>
void read (Type &x)
{
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9')
c == '-' && (flag = true);
x = c - '0';
while ((c = getchar()) >= '0' && c <= '9')
x = (x << 1) + (x << 3) + c - '0';
flag && (x = ~x + 1);
}
template <class Type, class ...rest>
void read (Type &x, rest &...y) { read(x), read(y...); }
template <class Type>
void write (Type x)
{
x < 0 && (putchar('-'), x = ~x + 1);
x > 9 && (write(x / 10), 0);
putchar('0' + x % 10);
}
const int N = 2e5 + 10;
bool v[N];
int n, w[N];
int check (int k)
{
for (int i = 1; i < 2 * n; ++i) v[i] = w[i] <= k;
for (int i = 0; i < n; ++i)
if (v[n + i] == v[n + i + 1]) return v[n + i];
else if (v[n - i - 1] == v[n - i]) return v[n - i];
return w[1];
}
int main ()
{
read(n);
for (int i = 1; i < 2 * n; ++i) read(w[i]);
int l = 1, r = n * 2 - 1;
while (l < r)
{
int mid = l + r >> 1;
check(mid) ? r = mid : l = mid + 1;
}
write(l);
return 0;
}