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;
}

浙公网安备 33010602011771号