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
*/

浙公网安备 33010602011771号