题意
告诉你一个序列,不同的数字代表不同的种类的动物,你需要给每只动物上色
如果相邻两个动物种类不同,那么他们涂的颜色也必须是不同的
给定的序列首尾相连,即最后一个与第一个也是相邻的
问最少需要多少种颜色去涂,且输出涂色方案
相同种类的动物可以涂不同的颜色
解题思路
显而易见,全部都是同种动物只需要一种颜色
如果出现两种动物,需要两种颜色,同种动物涂同种颜色即可
如果是三种以上的动物,因为给定的是一个环,首尾相连
所以需要注意,如果首尾动物不同,则首尾答案必须不同
如果不考虑首尾相连的情况,贪心可知只用两种颜色的话,只要相邻的两只动物不同色就可以
所以就可以在1和2之间来回切换,遇到不同就进行 p=3-p 的操作
最后判断,如果满足n>=3&&ar[1]!=ar[n]&&ans[1]==ans[n]
的话,说明需要更改尾部的颜色种类
但是如果随意更改种类可能导致其他部分中原本满足题意的涂色方案变成不满足题意
避免这种情况发生,又能考虑到,如果存在两个相邻的位置动物种类相同
那么从这个中间位置开始,两边任意一侧所有的1变成2,所有2变成1的话,相互之间的关系不会被改变
且题目有说明相同种类的动物可以涂不同的颜色,所以这种涂色方案满足题意
如果不存在两个相邻的位置动物种类相同,那么就没法翻转任意一侧,此时只能将种类数提升到3,最后一种动物涂色改成3才能满足题意
完整代码
#include<bits/stdc++.h>
using namespace std;
int ar[200050],ans[200050];
void solve(){
int n,i,p=1,kd=1,flag=0;
cin>>n>>ar[1];
ans[1]=1;//第一只动物直接处理成颜色1
for(i=2;i<=n;i++)//从2开始读入
{
cin>>ar[i];
if(ar[i]!=ar[i-1])
{
kd=2;//出现不同种类动物,种类数先变为2
p=3-p;
ans[i]=p;
}
else
{
flag=i;//记录相邻种类相同的位置
ans[i]=p;
}
}
if(n>=3&&ar[1]!=ar[n]&&ans[1]==ans[n])
{
if(flag)
{
for(i=flag;i<=n;i++)
ans[i]=3-ans[i];//flag其后全部翻转即可
}
else
{
kd=3;
ans[n]=3;
}
}
cout<<kd<<'
';
for(i=1;i<=n;i++)
cout<<ans[i]<<' ';
cout<<'
';
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--)
solve();
return 0;
}