codevs3044 矩形面积求并

由于05年的那道论文里的题我找不到(懒得找)

然后拿这题代替了一下,验证我算法的正确性

首先这题线段树是最优解就不用说了。

然后论文里有个坑爹题,把矩形染上颜色然后求每种颜色的面积。

这个时候线段树就要n^2*logn的复杂度啦

而下面这种方法依旧是n^2(然而我并没有找到那道题)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct seg{
	double l,r,x;
	int id,a,b;
	bool operator < (const seg &rhs)const{
		return x<rhs.x;
	}
}s[205];
bool ex[105];
int pa[205];
double hash[205];
int find(int x){
	return pa[x]==x?x:pa[x]=find(pa[x]);
}
void merge(int u,int v){
	u=find(u);v=find(v);
	if(u!=v){
		if(u>v)swap(u,v);
		pa[u]=v;
	}
}
double addseg(seg s){
	int last=s.a;
	double ans=0;
	for(int u=s.a;u<=s.b;){
		ans+=hash[u]-hash[last];
		merge(u,last);
		last=find(u);
		u=last+1;
	}
	return ans;
}
int n;
double work(){
	double ans=0;
	for(int i=1;i<=2*n;i++)pa[i]=i;
	for(int i=1;i<=2*n;i++)
	if(ex[s[i].id])
	ans+=addseg(s[i]);
	return ans;
}
double solve(){
	double ans=0;
	int j;
	for(int i=1;i<=2*n;i=j){
		j=i;
		while(j<=2*n&&s[i].x==s[j].x)
		ex[s[j++].id]^=1;
		ans+=work()*(s[j].x-s[i].x);
	}
	return ans;
}
void init(){
	double x1,x2,y1,y2;
	for(int i=1;i<=n;i++){
		scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
		s[2*i]=(seg){y1,y2,x1,i,0,0};
		s[2*i-1]=(seg){y1,y2,x2,i,0,0};
		hash[2*i]=y1;hash[2*i-1]=y2;
	}
	sort(hash+1,hash+2*n+1);sort(s+1,s+1+2*n);
	for(int i=1;i<=2*n;i++)
	s[i].a=lower_bound(hash+1,hash+1+2*n,s[i].l)-hash,
	s[i].b=lower_bound(hash+1,hash+1+2*n,s[i].r)-hash;
}
int main(){
	//freopen("a.in","r",stdin);
	while(scanf("%d",&n)&&n){
		init();
		printf("%.2lf\n",solve());
	}
	return 0;
}


你可能感兴趣的:(codevs3044 矩形面积求并)