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

Showball發表於2024-06-16

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

相關文章