• PA2019 Terytoria


    洛谷P5987 [PA2019] Terytoria

    题目大意

    在一个平面直角坐标系上,有一个长度为 X X X,宽度为 Y Y Y的地图,这个地图的左边界和右边界是连通的,下边界和上边界也是连通的。

    在地图中,有 X × Y X\times Y X×Y个格子以及 n n n个矩形,这些矩形的边与坐标轴平行。你只知道每个矩形两个对顶点的坐标,求被所有矩形覆盖住的格子数量的最大值?

    1 ≤ n ≤ 5 × 1 0 5 , 2 ≤ X , Y ≤ 1 0 9 1\leq n\leq 5\times 10^5,2\leq X,Y\leq 10^9 1n5×105,2X,Y109


    题解

    因为每个矩形在横坐标上是取两边或中间,在纵坐标上也是取两边或中间,所以横坐标和纵坐标是不相关的。我们把这些矩形分成映射在 x x x轴的线段和映射在 y y y轴的线段,则最终的答案为 x x x轴上能被所有线段覆盖的最大长度 × y \times y ×y轴上能被所有线段覆盖的最大长度。那么,我们就可以将横坐标和纵坐标分开来做。

    对横纵坐标进行离散化,对于离散化后的两个相邻的离散点连成的线段。那么,每种线段只有唯一的取法(取中间或者两边)才能覆盖这条由两个离散点连成的线段。我们用 01 01 01状态来表示每个矩形的覆盖情况( 0 0 0表示取两边, 1 1 1表示取中间),状态可以用哈希和差分来维护,然后用哈希表来存储对应状态的长度,边维护边取最大值。

    时间复杂度为 O ( n log ⁡ n + P ) O(n\log n+P) O(nlogn+P),其中 P P P为哈希表的大小。

    code

    #include
    using namespace std;
    const int N=500000,P=19260817,base=7;
    const long long mod1=998244353,mod2=1e9+7;
    int n,X,Y,tot=0,l[2*N+5],r[P+5],hv[2*N+5],w1[2*N+5],w2[2*N+5];
    long long re,ans=0,pw1[N+5],pw2[N+5];
    struct node{
    	int x,w,id;
    }x[2*N+5],y[2*N+5];
    bool cmp(node ax,node bx){
    	return ax.x<bx.x;
    }
    void add(int x,int h1,int h2,int vt){
    	l[++tot]=r[x];
    	w1[tot]=h1;w2[tot]=h2;hv[tot]=vt;
    	r[x]=tot;
    }
    void pl(int h1,int h2,int vt){
    	int u=h1%P;
    	for(int i=r[u];i;i=l[i]){
    		if(w1[i]==h1&&w2[i]==h2){
    			hv[i]+=vt;
    			re=max(re,1ll*hv[i]);
    			return;
    		}
    	}
    	add(u,h1,h2,vt);
    	re=max(re,1ll*vt);
    }
    long long solve(node *a,int mx){
    	memset(r,0,sizeof(r));
    	re=0;tot=0;
    	long long h1=0,h2=0;
    	pl(0,0,a[1].x);
    	for(int i=1;i<2*n;i++){
    		h1=(h1+pw1[a[i].id]*a[i].w+mod1)%mod1;
    		h2=(h2+pw2[a[i].id]*a[i].w+mod2)%mod2;
    		pl(h1,h2,a[i+1].x-a[i].x);
    	}
    	pl(0,0,mx-a[2*n].x);
    	return re;
    }
    int main()
    {
    //	freopen("globe.in","r",stdin);
    //	freopen("globe.out","w",stdout);
    	scanf("%d%d%d",&n,&X,&Y);
    	for(int i=1,dx,dy,ux,uy;i<=n;i++){
    		scanf("%d%d%d%d",&dx,&dy,&ux,&uy);
    		if(dx>ux) swap(dx,ux);
    		if(dy>uy) swap(dy,uy);
    		x[i*2-1]=(node){dx,1,i};
    		x[i*2]=(node){ux,-1,i};
    		y[i*2-1]=(node){dy,1,i};
    		y[i*2]=(node){uy,-1,i};
    	}
    	sort(x+1,x+2*n+1,cmp);
    	sort(y+1,y+2*n+1,cmp);
    	pw1[0]=pw2[0]=1;
    	for(int i=1;i<=N;i++){
    		pw1[i]=pw1[i-1]*base%mod1;
    		pw2[i]=pw2[i-1]*base%mod2;
    	}
    	ans=solve(x,X)*solve(y,Y);
    	printf("%lld",ans);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
  • 相关阅读:
    浏览器网页上如何播放dash视频、hls(m3u8)视频和flv格式视频?
    计算机基本架构-时序逻辑电路回顾
    android背景音乐保活
    生物医药企业全域数据治理实践 | 爱分析研讨会
    io多路复用:select、poll和epoll
    Windows下的RabbitMQ安装教程(遇到很多无语的问题,已解决)
    Ask Milvus Anything!聊聊被社区反复@的那些事儿ⅠⅠ
    学会这些分析定位BUG小技巧,你离跨入中级测试还远吗?
    25期代码随想录算法训练营第十天 | 栈与队列 part 2
    hot100-最大正方形
  • 原文地址:https://blog.csdn.net/tanjunming2020/article/details/133892526