题目链接
题目大意
就是数组里一段数可以都变成他的中位数,问整个序列能不能变成k。可以变化很多次
题目思路
emmm,根本没什么思路,看了题解感觉根本想不到啊,但是仔细想想其实确实应该那么想。
先令a[i]==1(a[i]==k) a[i]==0(a[i]<k) a[i]==2(a[i]>k),因为是合并其实只要知道相对k的大小即可
其实肯定是想一次合并的时候先想合并区间小的,为什么呢,因为你区间太大,你不好想啊。。。那么首先考虑区间长度为2,你会发现要把他们全部变成1只有可能是1,2。你1,1变什么变。。。然后考虑区间长度为3,这个时候你会发现(0,1,2)以及里面包含2个及以上1都行,然后你会发现其实如果能变一堆2出来好像也不错,然后再和1和2两个合并就行。那么其实就很好想了。
那么只要包含1,并且如果一个长度为 3 的子区间中有 2 个数大于等于 k ,那么就能行
简单理解一下这个结论:
与 1 相邻有 2 那么就可以改掉它
-
如果我们两个 1 就显然可以改掉一个数,同理别的直接改就好了
-
{0,1,2} 直接中位数
-
{0,2,2} 我们改掉 0 变成 2 然后对于每个 0 我们都可以把它改 成 2,直到找到 1
代码
#include<cstdio>
using namespace std;
const int maxn=1e5+5;
int t,n,k,a[maxn];
int main(){
scanf("%d",&t);
while(t--){
bool flag1=0,flag2=0;
scanf("%d %d",&n,&k);
for(int i=2;i<=n+1;i++){//防止数组下标为负数
scanf("%d",&a[i]);
if(a[i]<k){
a[i]=0;
}else if(a[i]==k){
a[i]=1;
flag1=1;
}else{
a[i]=2;
}
if(n==1||((a[i]>=1)+(a[i-1]>=1)+(a[i-2]>=1))>=2){//注意还有一个元素的情况
flag2=1;
}
}
printf("%s\n",(flag1&flag2)?"yes":"no");
}
return 0;
}