[AGC006D] Median Pyramid Hard 题解
题目链接:[AGC006D] Median Pyramid Hard
题意:
给出一个 \(N~(1 \le N \le 10^5)\) 层的方格金字塔,自顶向下依次标号为第 \(1\) 到第 \(N\) 层。
其中第 \(i~(1 \le i \le N)\) 层有 \(2i - 1\) 个方格(具体形态见下面的图)
第 \(N\) 层有一个 \(1\) 到 \(2N-1\) 的排列,其他层的数字按以下规则生成:
- 方格 \(b\) 中填写的整数,是方格 \(b\) 正下方、左下方和右下方方格中所写整数的中位数。
现在给出第 \(N\) 层的数字,请你求第一层的数字。
考虑二分最上层这个数 \(\ge x\),然后令 \(\ge x\) 的数为 \(1\) ,\(<x\) 的的数为 \(0\) 。
那么原题可以转化为,每次操作对于相邻的三个数,
如果 \(1\) 的个数 \(\ge 3\) 则为 \(1\) ,否则为 \(0\) ,最终最上面的那个数是 \(0\) 还是 \(1\) 。
这样问题就变成了 \(0,1\) 序列如何快速判断了,接下来就是找规律了,请参考 link 或者下图
时间复杂度 \(\mathcal{O}(n \log n)\) ,当然这题还有 \(\mathcal{O}(n)\) 的解法,也是基于这一规律的。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x, int y) { x < y ? x = y : 0; }
void down(int &x, int y) { x > y ? x = y : 0; }
#define rep(i, a, b) for(int i = (a), i##END = (b); i <= i##END; i++)
#define Rep(i, a, b) for(int i = (a), i##END = (b); i >= i##END; i--)
#define N ((int)(2e5 + 15))
int n, a[N], b[N];
bool check(int x)
{
rep(i, 1, n * 2 - 1) b[i] = (a[i] >= x);
rep(i, 0, n - 2)
{
if(b[n + i] == b[n + i + 1]) return b[n + i];
if(b[n - i] == b[n - i - 1]) return b[n - i];
} return b[1];
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
cin >> n;
rep(i, 1, n * 2 - 1) cin >> a[i];
int l = 1, r = (n << 1) - 1;
while(l < r)
{
int mid = (l + r + 1) >> 1;
check(mid) ? l = mid : r = mid - 1;
}
cout << l << '\n';
return 0;
}
参考文献
就是上面那个link。
题外话:
没图片,但是推歌。