ABC G 玄学TLE
  • 板块学术版
  • 楼主xzf888
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/4/13 21:59
  • 上次更新2024/4/13 22:00:27
查看原帖
ABC G 玄学TLE
1217150
xzf888楼主2024/4/13 21:59

本人在使用 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;
}
2024/4/13 21:59
加载中...