AGC006D Median Pyramid Hard

给出一个底座长度为 \(2*n-1\) 的金子塔。

除了最底下一层,上面格子的值是下一层格子和左右两边格子的中位数。

给出最底下一层是一个 \(1\)\(2\times n-1\) 的 permutation,求金字塔顶端的数字是啥。

\(1\leq n\leq 10^5, 1\leq a_1,a_2,\cdots,a_{2n-1}\leq2n-1\)

因为只有大小关系是重要的,所以可以考虑二分。

此时就会发现用 \(O(\log n)\) 的时间复杂度把问题转化成了只有 \(01\) 的序列,这个 payoff 是可以接受的。

\(01\) 的序列是 \(0\) 代表 \(a_i <p\)\(1\) 代表 \(a_i\geq p\) ,需要最底层是 \(1\)

然后我就卡在这一步了 Q^Q,其实根据我 \(B\) 题的发现,就是最地面一层 \(a_n\) 以及左右两边有一个格子和 \(a_n\) 相同。就是 \(00\) 或者 \(11\),如果是 \(00\),最底层是 \(0\) ;如果是 \(11\) ,最顶层是 \(11\),可以手动画一画。

那么可以考虑剩下的情况是什么,中间以及两边是 \(101\),或者是 \(010\),这种 \(01\) 交替的。如果 \(1\)\(2n-1\) 都是 \(01\) 交替的呢,\(101\) 答案是 \(1\), \(010\)\(0\),所以答案是最外层的数值是啥,也就是 \(a_1\) 或者 \(a_{2n-1}\) 的值。

那剩下的情况呢,如果某一位置破坏了呢?从中间往两边开始看。

如果当前是 \(11010\), 发现最后是 \(1\) ; 如果当前是 \(00101\),最后是 \(0\)

此时发现,找到两边第一个破坏当前 \(01\) 交替情况的数,如果是 \(0\) ,那么顶端就是 \(0\);如果是 \(1\),那么顶端就是 \(1\).

这样就可以 \(O(n)\) 地判断啦 o( ̄▽ ̄)ブ

时间复杂度: \(O(n\log n)\)

空间复杂度: \(O(n)\)

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n;
int a[2*N+5],b[2*N+5];
bool chk(int val){
	for(int i=1;i<=2*n-1;i++)b[i]=a[i]>=val;
//	cerr<<"val="<<val<<endl;
//	for(int i=1;i<=2*n-1;i++)cerr<<b[i]<<" ";cerr<<endl; 
	int cen=b[n],t=cen^1;
	for(int i=1;i<n;i++){
//		cerr<<t<<" "<<b[n-i]<<" "<<b[n+i]<<endl; 
		if(b[n-i]!=t)return b[n-i];
		if(b[n+i]!=t)return b[n+i];
		t=t^1;
	}
//	cerr<<"ok!\n";
	return b[1];
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=2*n-1;i++)scanf("%d",&a[i]);
//	for(int i=1;i<=2*n-1;i++)cerr<<chk(i)<<" ";cerr<<endl;
//	cerr<<chk(6)<<endl;
//	return 0;
	int low=2,high=2*n-1,ans=2;
	while(low<high){
		int mid=low+high>>1;
		if(chk(mid)){
			low=mid+1;
			ans=max(ans,mid);
		}else high=mid;
	}
	printf("%d\n",ans);
	return 0;
} 
/*
5
1 2 3 4 8 9 5 6 7
*/
posted @ 2026-03-31 01:57  xyangh  阅读(13)  评论(0)    收藏  举报