扫描线

其实并不能很熟练的写出代码,开此博客简单整理一下代码实现。

扫描线使用线段树的操作来实现。

对于这个线段树,可不是简单的线段树。我们维护的区间也很神奇……

对于 (l,r) 我们其实维护的是区间 (left[que[l],que[r+1] ight))

因为对于每一个区间加操作,一定会有一个相对应的区间减操作,所以标记不必下移,也不必更新……

在对边进行排序的时候,需要按照两个关键字进行排序

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

#define int long long
#define mid (l+r>>1)

using namespace std;

int read()
{
	int a = 0,x = 1;char ch = getchar();
	while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
	while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
	return a*x;
}
const int N=1e6+7;
struct node{
	int l,r,h,x;
	friend bool operator < (node a,node b) {return a.h!=b.h?a.h < b.h:a.x>b.x;}
}arr[N];
int n,cnt,que[N],tot,ans;
int a[N],b[N],c[N],d[N];

int tre[N],lazy[N];

void pushup(int root,int l,int r)
{
	if(lazy[root]) tre[root] = que[r+1]-que[l];
	else tre[root] = tre[root<<1]+tre[root<<1|1];
}

void modify(int root,int l,int r,int L,int R,int x)
{
	if(que[l] >= R || que[r+1] <= L) return;
	if(que[l] >= L && que[r+1] <= R) {
		lazy[root] += x;
	} else {
		modify(root<<1,l,mid,L,R,x);
		modify(root<<1|1,mid+1,r,L,R,x);
	}
	pushup(root,l,r);
}

void solve()
{
	for(int i = 1,tmp=0;i <= tot;i ++) {
		modify(1,1,cnt-1,arr[i].l,arr[i].r,arr[i].x);
		ans += abs(tmp-tre[1]);
		tmp = tre[1];
	}
}

signed main()
{
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	n = read();
	for(int i = 1;i <= n;i ++) {
		a[i] = read(),b[i] = read(),c[i] = read(),d[i] = read();
	}

	for(int i = 1;i <= n;i ++){
		que[++cnt] = a[i],que[++cnt] = c[i];
		arr[++tot] = (node){a[i],c[i],b[i],1};
		arr[++tot] = (node){a[i],c[i],d[i],-1};
	}
	sort(que+1,que+1+cnt);
	cnt = unique(que+1,que+1+cnt) - que - 1;
	que[0] = -1e18,que[cnt+1] = 1e18;
	sort(arr+1,arr+1+tot);
	solve();

	tot = cnt = 0;
	for(int i = 1;i <= n;i ++){
		que[++cnt] = b[i],que[++cnt] = d[i];
		arr[++tot] = (node){b[i],d[i],a[i],1};
		arr[++tot] = (node){b[i],d[i],c[i],-1};
	}
	sort(que+1,que+1+cnt);
	cnt = unique(que+1,que+1+cnt) - que - 1;
	que[0] = -1e18,que[cnt+1] = 1e18;
	sort(arr+1,arr+1+tot);
	solve();
	printf("%lld",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/nao-nao/p/14034620.html