Orac and Medians 题解

传送门

观察与思考后可得以下结论:

设序列中的一个子区间中大于等于 \(k\) 的个数有 \(a\) 个,小于 \(k\) 的个数有 \(b\) 个。

  • \(a>b\),则这个区间可以全部变成大于等于 \(k\) 的数

  • \(b=0\),则一定可以在保证这段区间含 \(k\) 的情况下把这段区间全部变成 \(k\)

结论 \(2\) 证明:考虑一个仅有两个数的序列 \(k,k+x\)\(x \in[0,inf]\)。则其中位数一定为 \(k\)。所以对于一个除了 \(k\) 以外全都大于 \(k\) 的序列一定可以反复用这样的方式将其全部变成 \(k\)

所以如果这个序列有 \(k\) 的情况下,能找到一个子区间使得 \(a>b\) 的话,则一定合法。

发现这种子区间只会由形如 \(k+x,k-x,k+x\)\(k+x,k+x\)\(x \in[0,inf]\) 的形式叠加构成。把序列扫一遍即可。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x7fffffff
const ll maxn=1e5+10;
ll a[maxn];
ll T,n,k;
inline ll in() {
	char a=getchar();
	ll v=0,f=1;
	while (a>'9'||a<'0') {if (a=='-') f=-1;a=getchar();}
	while (a>='0'&&a<='9') {v=(v<<3)+(v<<1)+a-'0';a=getchar();}
	return v*f;
}
inline void write(ll x) {
	if (x>9) write(x/10);
	putchar('0'+(x%10));
} 
signed main(){
	T=in();
	while (T--) {
		n=in(),k=in();a[n+1]=a[n+2]=0;
		ll flag=0,tot=0;
		for (ll i=1;i<=n;++i) a[i]=in();
		for (ll i=1;i<=n;++i) {
			if ((a[i]>=k&&a[i+1]>=k)||(a[i]>=k&&a[i+2]>=k)) tot++;
			if (a[i]==k) flag=1;
		}
		if (!flag||(tot==0&&n>=2)) {puts("no");}
		else puts("yes");
	} 
	return 0;
}
posted @ 2023-10-31 14:41  Pwtking  阅读(25)  评论(0)    收藏  举报