DTOJ#5330. 展览会

题目链接
题解:
首先,最小生成树不能不会 boruvka 算法。这个算法虽然难写,但扩展性(适用性)很强。即这种无法预处理出所有边的题,基本上都是这个算法。而且复杂度也是 O ( n log ⁡ n ) O(n\log n) O(nlogn)
这个算法其实就是 prim 算法的升级版
回到这题,我们只需支持 log ⁡ n \log n logn 内快速查询与一个集合中的一条线段有相交的另一个集合的线段标号即可。考虑用线段树。
首先考虑 l i ≤ l j ≤ r i ≤ r j l_i\leq l_j\leq r_i\leq r_j liljrirj 的情况,这时把线段按集合染色,每次查询 ≥ l j \geq l_j lj 的最小 r i r_i ri,即按 l j l_j lj 排序,每次在 r j r_j rj 处插入 r j r_j rj 即可 。

#include<bits/stdc++.h>
#define N 100005
using namespace std;
const int inf=1061109567;
inline int read(){
    
    
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){
    
    if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){
    
    x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int cl[N],fa[N],b[N<<1],tot,n;
inline int get(int x){
    
    
	return fa[x]==x?x:fa[x]=get(fa[x]);
}
inline int to(int x){
    
    return lower_bound(b+1,b+1+tot,x)-b;}
struct node{
    
    
	int l,r,id;
}ex[N];
bool cmpl(node a,node b){
    
    if(a.l==b.l)return a.r>b.r;return a.l<b.l;}
bool cmpr(node a,node b){
    
    if(a.r==b.r)return a.l<b.l;return a.r<b.r;}

struct seg{
    
    
	int l,r;
	int minn[2][2],maxn[2][2],lazy;
}t[N<<3];
inline void clea(int p){
    
    
	memset(t[p].minn,0x3f,sizeof(t[p].minn));
	memset(t[p].maxn,0,sizeof(t[p].maxn));
	t[p].lazy=0;
}
void build(int p,int l,int r){
    
    
	clea(p);t[p].l=l;t[p].r=r;
	if(l==r)return ;
	int mid=(l+r)>>1;
	build(p<<1,l,mid);build(p<<1|1,mid+1,r);
}
inline void up_min(int p,int val,int c){
    
    
	if(val<t[p].minn[0][0]){
    
    
		if(c!=t[p].minn[0][1]){
    
    
			t[p].minn[1][0]=t[p].minn[0][0];
			t[p].minn[1][1]=t[p].minn[0][1];
		}
		t[p].minn[0][0]=val;t[p].minn[0][1]=c;
	}else{
    
    
		if(val<t[p].minn[1][0]){
    
    
			if(c!=t[p].minn[0][1]){
    
    
				t[p].minn[1][0]=val;t[p].minn[1][1]=c;
			}
		}
	}
}
inline void up_max(int p,int val,int c){
    
    
	if(val>t[p].maxn[0][0]){
    
    
		if(c!=t[p].maxn[0][1]){
    
    
			t[p].maxn[1][0]=t[p].maxn[0][0];
			t[p].maxn[1][1]=t[p].maxn[0][1];
		}
		t[p].maxn[0][0]=val;t[p].maxn[0][1]=c;
	}else{
    
    
		if(val>t[p].maxn[1][0]){
    
    
			if(c!=t[p].maxn[0][1]){
    
    
				t[p].maxn[1][0]=val;t[p].maxn[1][1]=c;
			}
		}
	}
}
inline void push(int p){
    
    
	if(t[p].lazy){
    
    
		t[p].lazy=0;
		clea(p<<1);clea(p<<1|1);
		t[p<<1].lazy=1;t[p<<1|1].lazy=1;
	}
}
void ch_min(int p,int l,int val,int c){
    
    
	if(t[p].l==t[p].r){
    
    
		up_min(p,val,c);
		return ;
	}
	push(p);
	int mid=(t[p].l+t[p].r)>>1;
	up_min(p,val,c);
	
	if(l<=mid)ch_min(p<<1,l,val,c);
	else ch_min(p<<1|1,l,val,c);
}
void ch_max(int p,int l,int val,int c){
    
    
	if(t[p].l==t[p].r){
    
    
		up_max(p,val,c);
	    return ;
	}
	push(p);
	int mid=(t[p].l+t[p].r)>>1;
	up_max(p,val,c);
	if(l<=mid)ch_max(p<<1,l,val,c);
	else ch_max(p<<1|1,l,val,c);
}

pair<int, int> ask_min(int p,int l,int r,int c){
    
    
	if(t[p].l>=l&&t[p].r<=r){
    
    
		if(t[p].minn[0][1]!=c)return make_pair(t[p].minn[0][0],t[p].minn[0][1]);
		return make_pair(t[p].minn[1][0],t[p].minn[1][1]);
	}
	push(p);
	int mid=(t[p].l+t[p].r)>>1;
	pair<int, int> minn,now;minn.first=inf;
	if(l<=mid){
    
    now=ask_min(p<<1,l,r,c);if(minn.first>now.first)minn=now;}
	if(r>mid){
    
    now=ask_min(p<<1|1,l,r,c);if(minn.first>now.first)minn=now;}
	return minn;
}
pair<int, int> ask_max(int p,int l,int r,int c){
    
    
	if(t[p].l>=l&&t[p].r<=r){
    
    
		if(t[p].maxn[0][1]!=c)return make_pair(t[p].maxn[0][0],t[p].maxn[0][1]);
		return make_pair(t[p].maxn[1][0],t[p].maxn[1][1]);
	}
	push(p);
	int mid=(t[p].l+t[p].r)>>1;
	pair<int, int> maxn,now;maxn.first=0;
	if(l<=mid){
    
    now=ask_max(p<<1,l,r,c);if(maxn.first<now.first)maxn=now;}
	if(r>mid){
    
    now=ask_max(p<<1|1,l,r,c);if(maxn.first<now.first)maxn=now;}
	return maxn;
}
pair<int, int> d[N];
int main(){
    
    
	n=read();
	for(int i=1;i<=n;++i){
    
    
		ex[i].l=read(),ex[i].r=read();--ex[i].r;
		b[++tot]=ex[i].l,b[++tot]=ex[i].r;
		ex[i].id=i;fa[i]=i;cl[i]=i;
	}
	sort(b+1,b+1+tot);
	tot=unique(b+1,b+1+tot)-b-1;
	build(1,1,tot);
	int res=n,cnt=n;pair<int, int> now;
	long long ans=0;
	for(int i=1;i<=n;++i)ex[i].l=to(ex[i].l),ex[i].r=to(ex[i].r);
	while(res>1){
    
    
		cnt=res;
		sort(ex+1,ex+1+n,cmpl);
		clea(1);
		t[1].lazy=1;
		for(int i=1;i<=n;++i)d[i].first=inf;
		for(int i=1;i<=n;++i){
    
    
			int l=ex[i].l,r=ex[i].r,x=ex[i].id;
			now=ask_min(1,l,r,cl[x]);
			if(now.first!=inf)now.first=now.first-b[l]+1;
			if(d[cl[x]].first>now.first)d[cl[x]]=now;
			
			now=ask_min(1,r,tot,cl[x]);
			if(now.first!=inf)now.first=b[r]-b[l]+1;
			if(d[cl[x]].first>now.first)d[cl[x]]=now;
			
			ch_min(1,r,b[r],cl[x]);
		}
		clea(1);
		t[1].lazy=1;
		sort(ex+1,ex+1+n,cmpr);
		for(int i=1;i<=n;++i){
    
    
			int l=ex[i].l,r=ex[i].r,x=ex[i].id;
			now=ask_min(1,l,r,cl[x]);
			if(d[cl[x]].first>now.first)d[cl[x]]=now;
			
			ch_min(1,l,b[r]-b[l]+1,cl[x]);
		}
		for(int i=n;i;--i){
    
    
			int l=ex[i].l,r=ex[i].r,x=ex[i].id;
			now=ask_max(1,l,r,cl[x]);
			if(now.first!=0)now.first=b[r]-now.first+1;
			else now.first=inf;
			if(d[cl[x]].first>now.first)d[cl[x]]=now;
			
			ch_max(1,l,b[l],cl[x]);
		}
		for(int i=1;i<=n;++i){
    
    
			if(cl[i]==i&&d[i].first!=inf){
    
    
				
				int x=get(i),y=get(d[i].second);
				if(x!=y){
    
    
					ans=ans+1ll*d[i].first;
					fa[x]=y;
					--res;
				}
			}
		}
		for(int i=1;i<=n;++i)cl[i]=get(i);
		if(cnt==res){
    
    
			puts("-1");
			return 0;
		}
	}
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CSDNzhanghongyu/article/details/114437130
今日推荐