CF2003F Turtle and Three Sequences 题解

这一道题我们发现之间连边肯定是不行的,这种题肯定有很多边是没用的,考虑三条两两相交的边,如果需要连边,肯定是连最小的两条边即可。这样我们就可以想到,可以用扫描线维护每一个线段的存在的集合,每一个边只需要它在集合中的前驱和后继即可,其他的边都是没有用的,有更好的替代。时间复杂度 \(O(n\log n)\)

代码很简单:

#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int N=5E5+5;

int T,n;
pii e[N*2];
int c[N*2],cnt1,cnt2,ans,fa[N],a[N];
int l[N],r[N];
multiset<pii>st;
struct node{
	int w,x,y;
	bool operator < (const node &a)const{
		return w>a.w;
	}
};
priority_queue<node>q;
int cnt=0;
int find(int x){
	return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
	x=find(x),y=find(y);
	if(x!=y)fa[x]=y,cnt++;
}
int main(){
	cin>>T;
	while(T--){
		scanf("%d",&n);
		cnt1=0,cnt2=0;
		st.clear();
		for(int i=1;i<=n;i++){
			scanf("%d%d%d",&l[i],&r[i],a+i);
			e[++cnt1]={l[i],i};
			e[++cnt1]={++r[i],-i};
			c[++cnt2]=l[i];
			c[++cnt2]=r[i];
		}	
		sort(c+1,c+cnt2+1);
		cnt2=unique(c+1,c+cnt2+1)-c-1;
		sort(e+1,e+cnt1+1);
		for(int i=1;i<=cnt1;i++){
			if(e[i].second >0){
				st.insert({a[e[i].second],e[i].second});
				auto it=st.find({a[e[i].second],e[i].second});
				if(it!=st.begin())
					q.push({abs(prev(it)->first-it->first),prev(it)->second,it->second});
				if(next(it)!=st.end())
					q.push({abs(next(it)->first-it->first),next(it)->second,it->second});
				
			}
			else 
				st.erase(st.find({a[-e[i].second],-e[i].second}));
		}
		for(int i=1;i<=n;i++)fa[i]=i;
		cnt=0,ans=0;
		while(!q.empty()){
			node tmp=q.top();
			q.pop();
			if(find(tmp.x)==find(tmp.y ))continue;
			else merge(tmp.x ,tmp.y ),ans+=tmp.w;
		}
		if(cnt<n-1)puts("-1");
		else cout<<ans<<endl;
	}
	return 0;
}

posted @ 2025-08-28 10:18  hnczy  阅读(9)  评论(0)    收藏  举报