ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

离散化扫描线

2022-01-31 17:03:45  阅读:179  来源: 互联网

标签:个点 int 距离 离散 扫描线 区间 include


 这是一道需要离散化后的扫描线模板题,但是这道题有一个细节非常重要,所以拿出来单独说一下,扫描线的基本实现原理我就不赘述了,如果还有不明白的小伙伴可以看下我之前的介绍扫描线的博客,下面是地址:油漆面积(扫描线)_AC__dream的博客-CSDN博客

这两道题最大的区别就是这道题目的数据范围是1e9,显然不能直接建立这么大的线段树,需要我们先对给出的数据进行离散化,然后再按照正常的扫描线来进行处理

但是大家有没有发现扫描线要求我们维护的是线段,而不是一般的点,就比如我们离散化后的点一共有4个,假如我们对区间[1,3]进行修改,那么最后应该是对[1,2]和[3,3]两个区间分别进行修改,但是大家有没有发现一个问题,如果说区间[1,2]表示第1和2两个点的距离,那么区间[3,3]表示的岂不是3和3两个点的距离了?那这样满足左右端点相同的区间的距离岂不是一直是0了?况且我们永远处理不到2和3的距离,所以这样一定是会错的,那应该怎么办呢?如果说我们令线段树区间[l,r]表示的是第l个点和r+1个点之间的距离的话,那么任何一个区间都能够被表示了。而这恰恰是我在油漆面积那道题中忘记说明的非常重要的一点,因为拿到题目没有离散化,所以直接每两个相邻点之间的距离就是1,因为线段树区间[l,r]表示的是第l个点和第r+1个点之间的距离,所以距离就是(r+1)-l。

下面是这道题目的代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
#define int long long
const int N=1e6+10;
int l[N],r[N],cnt[N],len[N];
vector<int>alls;
int find(int x)
{
	return lower_bound(alls.begin(),alls.end(),x)-alls.begin()+1;
}
struct edge{
	int x,yn,yx,k;
}p[N];
bool cmp(edge a,edge b)
{
	return a.x<b.x;
}
void pushup(int id)
{
	if(cnt[id])	 len[id]=alls[r[id]]-alls[l[id]-1];//点区间[l[id],r[id]]实际表示的是线段区间[alls[l[id]-1],alls[r[id]]] 
	else if(l[id]==r[id]) len[id]=0;
	else len[id]=len[id<<1]+len[id<<1|1];
}
void build(int id,int L,int R)
{
	l[id]=L;r[id]=R;cnt[id]=len[id]=0;
	if(L==R) return ;
	int mid=L+R>>1;
	build(id<<1,L,mid);
	build(id<<1|1,mid+1,R);
}
void update_interval(int id,int L,int R,int k)
{
	if(l[id]>=L&&r[id]<=R)//当前区间完全在目标区间中 
	{
		cnt[id]+=k;
		pushup(id);
		return ;
	}
	int mid=l[id]+r[id]>>1;
	if(mid>=L) update_interval(id<<1,L,R,k);
	if(mid+1<=R) update_interval(id<<1|1,L,R,k);
	pushup(id);
}
signed main()
{
	int n;
	cin>>n;
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		int x1,y1,x2,y2;
		scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
		alls.push_back(y1);alls.push_back(y2);;
		p[++cnt]={x1,y1,y2,1};
		p[++cnt]={x2,y1,y2,-1};
	}
	sort(p+1,p+cnt+1,cmp);
	sort(alls.begin(),alls.end());
	alls.erase(unique(alls.begin(),alls.end()),alls.end());
	for(int i=1;i<=cnt;i++)
	{
		p[i].yn=find(p[i].yn);
		p[i].yx=find(p[i].yx);
	}
	build(1,1,alls.size());
	long long ans=0;	
	for(int i=1;i<=cnt;i++)
	{
		if(i>1) ans+=(p[i].x-p[i-1].x)*len[1];
		update_interval(1,p[i].yn,p[i].yx-1,p[i].k);
	}
	printf("%lld",ans);
	return 0;
}

标签:个点,int,距离,离散,扫描线,区间,include
来源: https://blog.csdn.net/AC__dream/article/details/122760563

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有