Codeforces Round #641 (Div. 2) D. Orac and Medians 题解(思维)

题目链接

题目大意

就是数组里一段数可以都变成他的中位数,问整个序列能不能变成k。可以变化很多次

题目思路

emmm,根本没什么思路,看了题解感觉根本想不到啊,但是仔细想想其实确实应该那么想。

先令a[i]==1(a[i]==k) a[i]==0(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. 如果我们两个 1 就显然可以改掉一个数,同理别的直接改就好了

  2. {0,1,2} 直接中位数

  3. {0,2,2} 我们改掉 0 变成 2 然后对于每个 0 我们都可以把它改 成 2,直到找到 1

代码

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

你可能感兴趣的:(思维)