CF1754C2 题解
简单版
在赛时写这题的我,想说: 这就是一个诈骗题!!!!
这题相对于简单版 最大的难点就是在处理0上,但两者实际的处理方法是一样的,所以我们先讲简单版。
简单版题目大意:
给出了一个只有
首先可以知道,在区间长度为奇数时,无解。 因为在这种情况下,无论如何构造,一定会多出来一个数,所以无解。
由于这题没有对答案有限制,只要符合要求就行,所以我们将区间长度往小了想,只对每两个数进行讨论。于是有两种情况:
至此,简单版就讲完了。
那这题对于简单版难在哪呢?序列里不只有
详情见代码吧:
#include <bits/stdc++.h>
using namespace std;
int wz[200005],n,a[200005],b[200005],x[200005],L[200005],R[200005];
int main(){
int t;
cin >> t;
while(t--){
int n;
cin >> n;
int cnt=0,ok=0,len=0;
for (register int i=1;i<=n;i++){
cin >> a[i];
if (a[i]!=0) b[++cnt]=a[i],wz[cnt]=i;//记录每个非0位置的信息
}
if (cnt%2==1){
cout << -1 << endl;//无解
continue ;
}
for (register int i=1;i<=cnt;i+=2){
if (b[i]!=b[i+1]){//第二种情况
for (register int j=wz[i-1]+1;j<=wz[i+1];j++){
L[++len]=R[len]=j;//每段单独分
}
}
else {
if (wz[i]+1==wz[i+1]) L[++len]=wz[i-1]+1,R[len]=wz[i+1];//相邻就直接分,注意要从上个非0位置+1开始
else {
for (register int j=wz[i-1]+1;j<=wz[i];j++) L[++len]=R[len]=j;//i之前全部单独分
for (register int j=wz[i]+1;j<=wz[i+1]-2;j++) L[++len]=R[len]=j;
L[++len]=wz[i+1]-1,R[len]=wz[i+1];//给第i+1个非零位置前留下一个0使它在区间里的长度变为偶数
}
}
}
if (R[len]<n){
L[len+1]=R[len]+1,R[len+1]=n;
len++;//可能最后一个非零数后面还有,单独再开一段
}
cout << len << '\n';
for (register int i=1;i<=len;i++) cout << L[i] << ' ' << R[i] << endl;
}
}