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;
}

浙公网安备 33010602011771号