AT2165 Median Pyramid Hard [二分答案]

Median Pyramid HardMedian Pyramid Hard


color{blue}{最初想法}

每次往上走, 最小值 与 最大值 都不会往上传, 于是就以为每次将最大值最小值去掉就好了, 即输出中位数…

:错因: 往上走时, 可能有数字重复地往上走, 出现了重复, 每次上去的就不一定是极值了.

color{red}{正解部分}

二分答案,
设二分出的答案为 midmid,
则将原来的三角形中 大于等于 midmid 的数字设为 11, 其余设为 00 .

:,.规律:若存在两个相邻的相同数字, 则往上将继续出现两个相同数字相邻的形势.

LuoguLuogu 题解上的图.

观察图可知, 哪种连续的数字离中轴较近, 则第一层为那种数字 .

于是只需要 O(N)O(N) 判断哪种数字离中轴最近即可 .

加上二分 总时间复杂度 O(NlogN)O(NlogN) .

:特殊情况:

同样是 LuoguLuogu 题解上的图

这个时候没有连续的 0011, 只需要看第一个元素是什么就可以了.


color{red}{实现部分}

check:check函数:

判断时可以不需要从左向右不断取 minmin 求最小值 .

可以直接从小到大枚举距离, 若有连续的数字, 直接返回即可,
若始终没有连续的数字, 为特殊情况, 特殊处理.

:左右端点的移动:

  • 若第 11 层为 11, 说明 真正答案 大于等于 xx, 需要将二分左端点右移.
  • 反之 右端点 左移.
#include<bits/stdc++.h>
#define reg register

const int maxn = 2e5 + 5; //!

int N;
int A[maxn];
int B[maxn];

bool chk(int x){
        for(reg int i = 1; i <= 2*N-1; i ++) B[i] = (A[i]>x);
        for(reg int d = 1; d < N; d ++)
                if((B[N+d-1]&&B[N+d]) || (B[N-d+1]&&B[N-d])) return 1;
                else if(((!B[N+d-1])&&(!B[N+d])) || ((!B[N-d+1])&&(!B[N-d]))) return 0;
        return B[1];
}

int main(){
        scanf("%d", &N);
        for(reg int i = 1; i <= 2*N-1; i ++) scanf("%d", &A[i]);
        int l = 1, r = 2*N-1;
        while(l < r){
                int mid = l+r >> 1;
                if(chk(mid)) l = mid + 1;
                else r = mid;
        }
        printf("%d
", l);
        return 0;
}

Why Wa?color{red}{Why Wa?↓}

#include<bits/stdc++.h>
#define reg register

const int maxn = 2e5 + 5; //!

int N;
int A[maxn];
int B[maxn];

bool chk(int x){
        for(reg int i = 1; i <= 2*N-1; i ++) B[i] = (A[i]>=x);
        for(reg int d = 1; d < N; d ++)
                if((B[N+d-1]&&B[N+d]) || (B[N-d+1]&&B[N-d])) return 1;
                else if(((!B[N+d-1])&&(!B[N+d])) || ((!B[N-d+1])&&(!B[N-d]))) return 0;
        return B[1];
}

int main(){
        scanf("%d", &N);
        for(reg int i = 1; i <= 2*N-1; i ++) scanf("%d", &A[i]);
        int l = 1, r = 2*N-1;
        while(l < r){
                printf("%d %d
", l, r);
                int mid = l+r >> 1;
                if(chk(mid)) l = mid;
                else r = mid - 1;
        }
        printf("%d
", l);
        return 0;
}

原文地址:https://www.cnblogs.com/zbr162/p/11822546.html