CF D Wa on 31 求助玄关
  • 板块学术版
  • 楼主sbno333
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/7/19 01:41
  • 上次更新2024/7/19 09:12:58
查看原帖
CF D Wa on 31 求助玄关
416975
sbno333楼主2024/7/19 01:41

思路:从后往前操作,贪心的合并,使得合并后的新集合尽量小,编号 ii 操作最多判定 n2÷in^2\div i 的量级种连边。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
int a[1000009];
int fa[1000009];
int dx[1000009];
int getfa(int a){
	if(fa[a]==a){
		return a;
	}
	return fa[a]=getfa(fa[a]);
}
void merge(int x,int y){
	if(getfa(x)!=getfa(y)) 
	dx[getfa(y)]+=dx[getfa(x)];
	fa[getfa(x)]=getfa(y);
}
int n;
struct st{
	int v,ne;
}sd[1000009];
int inn;
int h[1000009];
void cr(){
	for(int i=0;i<=n+10;i++){
		h[i]=0;
	}
	inn=0;
}
void add(int u,int v){
	sd[++inn].v=v;
	sd[inn].ne=h[u];
	h[u]=inn;
}
pii an[1000009];
void _main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i]; 
	}
	for(int i=0;i<=n+10;i++){
		fa[i]=i,dx[i]=1;
		an[i]={0,0};
	}
	for(int i=n-1;i>=1;i--){
		cr();
		int sx;
		sx=(n+1)*(n+1)/i+1000;
		for(int j=1;j<=n;j++){
			for(int k=h[a[j]%i];k;k=sd[k].ne){
				if(getfa(sd[k].v)!=getfa(j)){
				
					if(an[i].first==0||dx[getfa(an[i].first)]+dx[getfa(an[i].second)]>dx[getfa(sd[k].v)]+dx[getfa(j)]){
						//cout<<sd[k].v<<"-"<<j<<endl;
						an[i]={sd[k].v,j};
					}
				}
				sx--;
				if(sx<0){
					break;
				}
			}
			if(sx<0){
				merge(an[i].first,an[i].second);
				//cout<<an[i].first<<" "<<an[i].second<<" "<<(getfa(an[i].first)!=getfa(an[i].second))<<endl;
				break;
			}
			add(a[j]%i,j);
		}
		if((getfa(an[i].first)!=getfa(an[i].second)))
		merge(an[i].first,an[i].second);
	}
	cout<<"YES"<<endl;
	for(int i=1;i<n;i++){
		cout<<an[i].first<<" "<<an[i].second<<endl;
	}
}
signed main(){
	int t;
	cin>>t;
	while(t--){
		_main();
	}
	return 0;
}
2024/7/19 01:41
加载中...