嘘~ 正在从服务器偷取页面 . . .

[AGC006D] Median Pyramid Hard 题解


[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。


题外话

没图片,但是推歌。


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录