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; }
|