CF 1981 C Turtle and an Incomplete Sequence(*1800) 构造

CF 1981 C Turtle and an Incomplete Sequence(*1800) 构造

题目链接

题意

给定一个长度为 \(n\) 的序列 \(a\) ,要求把 \(a\) 中所有的 \(-1\) 替换为任意正整数,且满足对于所有的 \(1 \le i \le n\), 那么 \(a_i= \lfloor \frac{a_{i+1}}{2} \rfloor\), 要么 \(a_{i+1} = \lfloor \frac{a_i}{2} \rfloor\)

思路

首先,容易发现每个连续的 \(-1\) 段的构造是独立的,相互不会影响。那么我们一段一段构造即可。

如果序列 \(a\) 全是 \(-1\), 那么我们构造形如 \(1,2,1,2,...,1,2\) 的序列即可。

不妨令区间左端点值为 \(L\), 右端点值为 \(R\) 。对于首段和尾段,我们直接从固定的值往前或往后构造即可。

一直除2即可,如果当前位为 \(1\) , 那就赋值为 \(2\) ,然后一直 \(1,2,1,2...\) 循环即可。

现在考虑中间段的情况。我们只需要将较大值进行同样的处理即可,不断缩小区间范围。最后判断是否满足题意即可。

代码:

void Showball(){
   int n;
   cin>>n;
   vector<int> a(n);
   for(int i=0;i<n;i++) cin>>a[i];
   if(count(all(a),-1)==n){
      for(int i=0;i<n;i++) a[i]=i%2+1;
   }else{
      for(int i=0,j=-1;i<=n;i++){
         if(i==n||~a[i]){
            if(j==-1){//首段
               for(int k=i-1;k>=0;k--){
                  a[k]=a[k+1]==1?2:a[k+1]/2;
               }
            }else if(i==n){//尾段
               for(int k=j+1;k<n;k++){
                  a[k]=a[k-1]==1?2:a[k-1]/2;
               }
            }else{//中间段
               int l=j,r=i;
               while(l+1<r){
                  if(a[l]>a[r]){
                     a[l+1]=a[l]==1?2:a[l]/2;
                     l++;
                  }else{
                     a[r-1]=a[r]==1?2:a[r]/2;
                     r--;
                  }
               }
               if(a[l]!=a[r]/2&&a[r]!=a[l]/2){
                  return cout<<"-1\n",void();
               }
            }
            j=i;
         }
      }
   }
   for(int i=0;i<n;i++) cout<<a[i]<<" \n"[i==n-1];
}
posted @ 2024-06-16 00:01  Showball  阅读(7)  评论(0编辑  收藏  举报