全球覆盖 哈希

全球覆盖 哈希

题目描述

小黑正在研发一款全球定位软件,想用它来定位小白的坐标。
具体来说,地球可以看做一个\(X \times Y\)的网格矩阵,横纵坐标范围分别是\([0, X)\)\([0, Y)\),由于地球是球形结构,网格的上边界和下边界是相通的,左边界和右边界也是相通的。
现在小黑获得了\(n\)组坐标对,每组坐标对含有两个点的坐标\((x_i,0 , y_i,0 ), (x_i,1 , y_i,1 )\),表示地球上一个两边平行于坐标轴的矩形的两个对角顶点,而小白就在这个矩形内部。
然而,由于地球是球形结构,确定了坐标对后仍然有多种可能的“矩形”(如下
图所示)。小黑想知道最多可能有多少面积的网格出现在所有“矩形”的交集之中,
以方便他确定小白的位置。每个单元格的面积为\(1\)
于是他把这个问题交给你了。

输入格式

从文件 \(globe.in\) 中读入数据。
第一行三个正整数\(n, X, Y\),含义如题目描述。
接下来n行,每行四个正整数\(x_i,0 , y_i,0 , x_i,1 , y_i,1\) ,描述一组坐标对。所有数据始终保
证有\(x_i,0 < x_i,1 , y_i,0 < y_i,1\)

输出格式

输出到文件 \(globe.out\) 中。
一行,一个整数,表示所求的答案。

样例 1 输入

2 10 7
2 1 8 6
4 2 5 4

样例 1 输出

15

样例 1 解释

样例中的情况和题目中图片一致,其中第三种情况的面积最大。

样例 2

见下发文件中的\(globe2.in\)\(globe2.ans\)

数据范围

对于前\(10\%\) 的数据,\(n ≤ 10\)
对于前\(20\%\) 的数据,\(n ≤ 20\)
对于另\(50\%\) 的数据,\(n ≤ 3000\)
对于\(100\%\) 的数据,\(n ≤ 500000,2 ≤ X, Y ≤ 10 9 , 0 ≤ x_0 , x_1 < X, 0 ≤ y_0 , y_1 < Y\)

分析

我们可以发现横纵坐标互不相关,因此可以对于横纵坐标分别枚举求出最大值,再相乘即可

现在考虑怎么单独求出横坐标或者纵坐标的最大值

显然,我们所选择的线段一定是被两组相邻的线段所截得的

而且如果我们要把多个线段拼到一起的话,这些线段必须满足截得它们的线段的价值相同

比如说上面这一幅图,如果我们去找能与\(1\)号线段合并的线段,那么我们就去看其它四条线段两端的颜色是否\(1\)好线段的颜色相同,我们发现\(5\)号线段满足这个条件,那么我们就把\(1\)号线段和\(5\)号线段合并

同理,我们还可以把\(2\)号线段和\(4\)号线段合并,而\(3\)号线段没有可以与它合并的

那么暴力的思路就是用\(n^2\)的效率去枚举两条线段看它们是否能合并在一起

实际上,我们可以对与每条线段取一个贡献的哈希值,将这些哈希值存在哈希表里,每次加入线段时遇到哈希值相同的就合并

合并时取一个最大值即可

代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
inline int read(){
	int x=0,fh=1;
	char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=2e6+5;
typedef unsigned long long ll;
const ll bas=131;
int ans=0;
struct m_hash{
	static const ll Mod=261807;
	struct asd{
		int next,jz;
		ll val;
	}b[maxn];
	int head[maxn],tot;
	m_hash(){
		memset(head,-1,sizeof(head));
		tot=1;
	}
	void ad(int cd,ll val){
		int now=val%Mod;
		for(int i=head[now];i!=-1;i=b[i].next){
			ll u=b[i].val;
			if(u==val){
				b[i].jz+=cd;
				ans=std::max(ans,b[i].jz);
				return;
			}
		}
		b[tot].val=val;
		b[tot].jz=cd;
		ans=std::max(ans,b[tot].jz);
		b[tot].next=head[now];
		head[now]=tot++;
	}
}mp1,mp2;
struct asd{
	int val,id,jud;
	asd(){}
	asd(int aa,int bb,int cc){
		val=aa,id=bb,jud=cc;
	}
}a[maxn],b[maxn];
bool cmp(asd aa,asd bb){
	return aa.val<bb.val;
}
int n,x,y;
ll mi[maxn];
int solve1(){
	std::sort(a+1,a+n*2+1,cmp);
	ll now=0;
	for(int i=2;i<=n*2;i++){
		now=now+mi[a[i-1].id]*a[i].jud;
		mp1.ad(a[i].val-a[i-1].val,now);
	}
	mp1.ad(a[1].val,0);
	mp1.ad(x-a[n*2].val,0);
	return ans;
}
int solve2(){
	ans=0;
	std::sort(b+1,b+n*2+1,cmp);
	ll now=0;
	for(int i=2;i<=n*2;i++){
		now=now+mi[b[i-1].id]*b[i].jud;
		mp2.ad(b[i].val-b[i-1].val,now);
	}
	mp2.ad(b[1].val,0);
	mp2.ad(y-b[n*2].val,0);
	return ans;
}
int main(){
	n=read(),x=read(),y=read();
	mi[0]=1;
	for(int i=1;i<=n;i++){
		a[i].val=read();
		b[i].val=read();
		a[i+n].val=read();
		b[i+n].val=read();
		a[i].id=b[i].id=a[i+n].id=b[i+n].id=i;
		a[i].jud=b[i].jud=1;
		a[i+n].jud=b[i+n].jud=-1;
		mi[i]=mi[i-1]*bas;
	}
	printf("%lld\n",1LL*solve1()*solve2());
	return 0;
}
posted @ 2020-09-08 20:47  liuchanglc  阅读(269)  评论(0编辑  收藏  举报