CF-1252H-Twin Buildings(扫描线+线段树)

题目链接:https://codeforces.com/contest/1252/problem/H

题目大意:给出n个矩形小岛,每个小岛有两个属性:长和宽。我们要建两座相同的房子,要求房子的面积最大。这里相同的房子意思是边长对应相等。问最大的面积是多少。可以将一个岛分成两半一边一个。

思路:将所有岛都放倒(长的边贴在x轴上)。然后找最大的重叠面积,即覆盖面积>=2的。最后和最大的单独岛比较一下就好了 。

注意有一个坑点,输出,如果直接输出%lf的话,可能会输出1.499999999999的情况,所以特判一下整数输出?学到了。。。

ACCode:

#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<time.h>
#include<math.h>
// srand((unsigned)time(NULL));rand();
      
#include<map>//unordered_map
#include<set>//multiset
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
 
#define ll long long
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define clean(a,b) memset(a,b,sizeof(a))
using namespace std;
      
const int MAXN=1e5+10;
//const int MAXM=10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
//unsigned register
// ios::sync_with_stdio(false)

struct SegTree{
	struct Tree{
		int l,r,flag;
		ll rl,rr;
		ll len1,len2;
	};
	Tree T[MAXN<<2];
	
	void PushUp(int rt){
		if(T[rt].flag) T[rt].len1=T[rt].rr-T[rt].rl;
		else if(T[rt].l+1==T[rt].r) T[rt].len1=0;
		else T[rt].len1=T[rt<<1].len1+T[rt<<1|1].len1;
		
		if(T[rt].flag>1) T[rt].len2=T[rt].rr-T[rt].rl;
		else if(T[rt].l+1==T[rt].r) T[rt].len2=0;
		else if(T[rt].flag==1) T[rt].len2=T[rt<<1].len1+T[rt<<1|1].len1;
		else T[rt].len2=T[rt<<1].len2+T[rt<<1|1].len2; 
	}
	void Build(ll l,ll r,int rt,ll A[]){
		T[rt].l=l;T[rt].r=r;T[rt].flag=0;
		T[rt].rl=A[l];T[rt].rr=A[r];
		T[rt].len1=T[rt].len2=0;
		if(l+1==r) return ;
		int mid=(l+r)>>1;
		Build(l,mid,rt<<1,A);Build(mid,r,rt<<1|1,A);
		PushUp(rt);
	}
	void Update(ll ql,ll qr,int val,int rt){
		if(ql<=T[rt].rl&&T[rt].rr<=qr){
			T[rt].flag+=val;PushUp(rt);
			return ;
		}
		if(qr<=T[rt<<1].rr) Update(ql,qr,val,rt<<1);
		else if(ql>=T[rt<<1|1].rl) Update(ql,qr,val,rt<<1|1);
		else{
			Update(ql,qr,val,rt<<1);
			Update(ql,qr,val,rt<<1|1);
		}PushUp(rt);
	}
	void Show(int rt){
		printf("l=%d r=%d rl=%d rr=%d len1=%d len2=%d flag=%d\n",T[rt].l,T[rt].r,T[rt].rl,T[rt].rr,T[rt].len1,T[rt].len2,T[rt].flag);
		if(T[rt].l==T[rt].r) return ;
		Show(rt<<1);Show(rt<<1|1);
	}
};
struct Line{
	ll x,y1,y2,flag;
	friend int operator < (Line a,Line b){
		return a.x<b.x;
	}
};
SegTree Seg;
Line l1[MAXN*2];
ll Y[MAXN*2];
int n;

int main(){
	while(~scanf("%d",&n)){
		ll ans=0;
		for(int i=1;i<=n;++i){
			ll x,y;scanf("%lld%lld",&x,&y);
			if(x<y) swap(x,y);
			ans=max(ans,1ll*x*y);
			l1[i].x=0;l1[i].y1=0;l1[i].y2=y;l1[i].flag=1;
			l1[i+n].x=x;l1[i+n].y1=0;l1[i+n].y2=y;l1[i+n].flag=-1;
			Y[i]=y;
		}Y[n+1]=0;
		sort(l1+1,l1+1+2*n);sort(Y+1,Y+1+n+1);
		int tmp=1;
		for(int i=2;i<=n+1;++i){
			if(Y[i]!=Y[tmp]) Y[++tmp]=Y[i];
		}Seg.Build(1,tmp,1,Y);
//		printf("ans=%.2lf\n",1.0*ans);
		for(int i=1;i<n*2;++i){
			ll l=l1[i].y1,r=l1[i].y2,flag=l1[i].flag;
			Seg.Update(l,r,flag,1);
			ll len=Seg.T[1].len2;
			ans=max(ans,2ll*l1[i+1].x*len);
		}
		if(ans%2) printf("%lld.5\n",ans/2ll);
		else printf("%lld.0\n",ans/2ll);
	}
}

/*
6
1000000000 100000
1000 1000000000
98765412 321654
65412378 1000000000
1 1
333333 3654987 
120000000 10000000


*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值