#构造,二分#[AGC006B] [AGC006D] Median Pyramid

Easy
Hard


分析(Easy)

\(X=1\)\(X=2n-1\)无解,否则在正中间构造\(X-1,X,X+1\)
其余位置升序铺入剩余数,
\(X-1\)左侧数大于\(X-1\)那么\(X-1\)\(X\)上方必定为\(X\)
\(X+1\)上方为\(X+1\),可以发现比原来更接近\(X\),显然到塔尖答案即为\(X\)
\(X+1\)右侧数小于\(X+1\)的情况同理


代码

#include <cstdio>
#define rr register
using namespace std;
int n,x,t;
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
signed main(){
	scanf("%d%d",&n,&x);
	if (x==1||x==2*n-1) return !puts("No");
	puts("Yes"),t=1;
	for (rr int i=1;i<n-1;++i){
		while (x-1<=t&&t<=x+1) ++t;
		print(t++),putchar(10);
	}
	print(x-1),putchar(10),
	print(x),putchar(10),
	print(x+1),putchar(10);
	for (rr int i=1;i<n-1;++i){
		while (x-1<=t&&t<=x+1) ++t;
		print(t++),putchar(10);
	}
	return 0;	
}

分析(Hard)

考虑二分答案,令\(b[i]=a[i]\leq ans\)
按照Easy越接近中间越有可能成为答案
所以越靠中间只要存在两个1,这个答案就可以被传上去,
否则如果存在两个0显然不行,否则如果都判断不了就用\(b[1]\)判断


代码(Hard)

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
int n,a[200011];
inline signed iut(){
	rr int ans=0,f=1; rr char c=getchar();
	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans*f;
}
inline bool check(int k){
	for (rr int i=0;i<n-1;++i){
		if ((a[n-i-1]>k&&a[n-i]>k)||(a[n+i]>k&&a[n+i+1]>k)) return 0;
		if ((a[n-i-1]<=k&&a[n-i]<=k)||(a[n+i]<=k&&a[n+i+1]<=k)) return 1;
	}
	return a[1]<=k;
}
signed main(){
	n=iut();
	for (rr int i=1;i<=n*2-1;++i) a[i]=iut();
	rr int l=2,r=2*(n-1);
	while (l<r){
		rr int mid=(l+r)>>1;
		if (check(mid)) r=mid;
		    else l=mid+1;
	} 
	return !printf("%d",l);	
}
posted @ 2021-03-05 20:31  lemondinosaur  阅读(49)  评论(0编辑  收藏  举报