本人在使用 Manacher 优化建图时使用了路径压缩+按秩合并的并查集并喜提 TLE,去掉按秩合并即可 AC,AC代码见下,取消注释那行的注释会 TLE,使用自己写的 swap 函数结果相同。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
int bucMex[1000000],r[1000000],s[1000000],fa[1000000],siz[1000000];
int mex(vector<int> v){
for(int i=0;i<=v.size();i++) bucMex[i]=0;
for(auto it:v){
if(it<=v.size()) bucMex[it]=1;
}
int ret=0;
while(bucMex[ret]) ret++;
return ret;
}
int find(int p){
if(fa[p]) return fa[p]=find(fa[p]);
return p;
}
void merge(int a,int b){
a=find(a),b=find(b);
if(a==b) return;
//if(siz[a]>siz[b]) swap(a,b);
fa[a]=b;
siz[b]+=siz[a];
}
bool same(int a,int b){
a=find(a),b=find(b);
return a==b;
}
vector<int> e[1000000];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++) siz[i]=1;
int p=0,mx=0;
for(int i=1;i<=n;i++){
cin>>r[i];
r[i]++;
int poi=1;
if(i<mx) poi=min(mx-i,r[2*p-i]);
if(poi>r[i]){
cout<<"No\n";
return 0;
}
while(poi<r[i]){
if(i+poi<=n&&i-poi>=1) merge(i+poi,i-poi);
poi++;
}
if(i+r[i]>mx){
mx=i+r[i];
p=i;
}
}
for(int i=1;i<=n;i++){
if(i-r[i]>=1&&i+r[i]<=n){
if(same(i-r[i],i+r[i])){
cout<<"No\n";
return 0;
}
e[find(i-r[i])].push_back(find(i+r[i]));
e[find(i+r[i])].push_back(find(i-r[i]));
}
}
memset(s,-1,sizeof(s));
cout<<"Yes\n";
for(int i=1;i<=n;i++){
if(s[find(i)]==-1){
vector<int> v;
for(auto it:e[find(i)]){
if(s[find(it)]!=-1) v.push_back(s[find(it)]);
}
s[find(i)]=mex(v);
}
cout<<s[find(i)]+1<<' ';
}
return 0;
}