一道具有一定的思维难度的题。(就是我太菜了)
小视野链接
洛谷链接
题目大意
(我懒得精简题意了,请看原题吧。。。)
题解
参考了部分大佬的做法:
先二分答案k,构造一个01串,把小于k的数设为0,否则设为1。这样,取中位数就等于取01序列的众数。这样如果01串中有相邻且相同的数,只要他没有被其他相邻且相同的数影响,就会成为顶上的数。又能进一步推出,如果01串中存在相邻且相同的数,顶上的答案就是离中间最近的相邻且相同的数。(好吧有点绕,见代码吧。。。)否则,01串的数字相互间隔,顶上的数为最左边的数。
(以上内容如果不懂,那很正常。。,最好手动模拟一下)
这样顶上的数为1,则正确答案比当前大(或相等),否则比当前小,进一步二分即可。
代码
#pragma GCC optimize(3)
#include<iostream>
#include<iomanip>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#define ll long long
#define db double
#define inf 200000
#define INF (int)1e8
#define mod (int)(1e9+7)
#define pi acos(-1)
#define rd(n) {n=0;char ch;int f=0;do{ch=getchar();if(ch=='-'){f=1;}}while(ch<'0'||ch>'9');while('0'<=ch&&ch<='9'){n=(n<<1)+(n<<3)+ch-48;ch=getchar();}if(f)n=-n;}
using namespace std;
int a[inf],p[inf];
int n;
bool check(int k){
for (int i=1;i<=n*2-1;i++){
p[i]=(a[i]>=k);
}
int posl=0,posr=n*2;
for (int i=n;i>=2;i--){
if (p[i]==p[i-1]){
posl=i;
break;
}
}
for (int i=n;i<n*2-1;i++){
if (p[i]==p[i+1]){
posr=i;
break;
}
}
if (posl==0 && posr==n*2){
return p[1];
}
return n-posl>posr-n?p[posr]:p[posl];
}
int main(){
rd(n)
for (int i=1;i<=n*2-1;i++){
rd(a[i])
}
int l=2,r=n*2-2,ans;
while (l<=r){
int mid=(l+r)/2;
if (check(mid)){
ans=mid;
l=mid+1;
}
else{
r=mid-1;
}
}
printf("%d\n",ans);
return 0;
}