H. Twin Buildings(贪心&扫描线)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了H. Twin Buildings(贪心&扫描线)相关的知识,希望对你有一定的参考价值。

H. Twin Buildings(贪心&扫描线)

1.贪心

分情况讨论:

  • 只在一个地(取最大值/2)即可。
  • 在两个地建。

第二种情况,不妨将所有陆地的长、宽交换,保证 l ≤ w l\\le w lw

然后按照 w w w从大到小排序,这样当前的 l l l一定是能包括在前面里面的, w w w的话就是取前缀的最大值,因为 w w w始终小于等于 l l l

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

参考代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
typedef long long ll;
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define pb push_back
ll t,n,cnt;
ll ans,maxx;
struct node{
	ll x;
	ll y;
}a[maxn];
bool cmp(node a,node b){
	return a.y>b.y;
}
int main(){
int n;
	cin >> n;
	ll ans = 0;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i].x >> a[i].y;
		ans = max(ans, a[i].x * a[i].y);
		if (a[i].x > a[i].y)
			swap(a[i].x, a[i].y);
	}
	sort(a + 1, a + n + 1,cmp);
	maxx = 0;
	for (int i = 1; i <= n; i++)
	{
		ans = max(ans, min(maxx, a[i].x) * a[i].y * 2);
		maxx = max(maxx, a[i].x);
	}
	if (ans % 2)
		printf("%lld.5\\n", ans / 2);
	else
		printf("%lld.0\\n", ans / 2);
	return 0;
}

2.扫描线

第二种情况,考虑考把所有矩形的左下角移动到原点,就是求两矩形的面积并。然后就是预处理入边,出边,排序,扫描线的裸题。

#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
*/

以上是关于H. Twin Buildings(贪心&扫描线)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5301(Buildings-贪心构造)

HDU-4296 Buildings 贪心 从相邻元素的相对位置开始考虑

[ 题解 ] [ 贪心 ] H. Roma and Changing Signs (待更名)

道具、TailwindCSS 和 Twin.Macro

UVA434 Matty‘s Blocks贪心

HDU2560 Buildings