AW247 亚特兰蒂斯(区间覆盖线段树)

题目地址


注意点:

  • 需要将y轴坐标离散化后映射到线段树上.

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int MAXN=2e5;
struct Point{
	double x,y,z;
	int k;
	bool operator <(Point another)const{
		return x<another.x;
	}
}a[MAXN];
struct Line{
	int l,r,cnt;
	double len;
}tr[MAXN<<3];
void build(int p,int l,int r){
	tr[p].l=l,tr[p].r=r,tr[p].cnt=0,tr[p].len=0;
	if(l!=r){
		int mid=(l+r)>>1;
		build(p<<1,l,mid);
		build((p<<1)|1,mid+1,r);
	}
} 
double raw[MAXN<<1];
void change(int p,int l,int r,double val){
	if(tr[p].l>=l&&tr[p].r<=r){
		tr[p].cnt+=val;
		if(tr[p].cnt){
			tr[p].len=raw[tr[p].r+1]-raw[tr[p].l];
		}else{
			if(tr[p].l!=tr[p].r){
				tr[p].len=tr[p<<1].len+tr[(p<<1)|1].len;
			}else tr[p].len=0;
		}
		return;
	}
	int mid=(tr[p].l+tr[p].r)>>1;
	if(l<=mid)change(p<<1,l,r,val);
	if(r>mid)change((p<<1)|1,l,r,val);
	tr[p].len=tr[p].cnt?raw[tr[p].r+1]-raw[tr[p].l]:tr[p<<1].len+tr[(p<<1)|1].len;
}
map<double,int> val;
int root=1;
int main(){
	int caseCnt=0;
	while(1){
		int n;
		scanf("%d",&n);
		if(n==0)break;
		for(int i=1;i<=n;i++){
			int k=i*2;
			double y,z;
			scanf("%lf%lf%lf%lf",&a[k-1].x,&y,&a[k].x,&z);
			raw[k-1]=a[k-1].y=a[k].y=y;
			raw[k]=a[k-1].z=a[k].z=z;
			a[k-1].k=1,a[k].k=-1;
		}
		n=n<<1;
		sort(raw+1,raw+n+1);
		int m=unique(raw+1,raw+1+n)-(raw+1);
		for(int i=1;i<=m;i++)val[raw[i]]=i;
		sort(a+1,a+1+n);
		build(root,1,m-1);
		double ans=0;
		for(int i=1;i<=n-1;i++){
			int y=val[a[i].y],z=val[a[i].z]-1;
			change(root,y,z,a[i].k);
			ans+=tr[root].len*(a[i+1].x-a[i].x);
		}
		printf("Test case #%d\n",++caseCnt);
		printf("Total explored area: %.2f\n\n",ans);
	}
	return 0;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值