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