【模板】 扫描线

模板题:https://www.luogu.org/problem/P5490 与 http://poj.org/problem?id=1151


扫描线从左向右扫,rwa[]数组表示整数值 i  对应的原始 y 坐标值。 c[i] 记录扫描线上第 i 段覆盖的次数,ans 每次累加上 len*(x2-x1)即可 ,朴素做法O(n^2) ,用线段树维护 c 数组后复杂度 O(n*longn)


//#include <bits/stdc++.h>
#include <iostream> 
#include <vector>
#include <algorithm>
#include <iomanip>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef long double ld;
const ll maxn = 1e6+100;

ll n,num,c[maxn];
ll x1[maxn],x2[maxn],y1[maxn],y2[maxn],raw[maxn];

struct sgt
{
	ll l,r,cnt;
	ll len;
}tree[maxn<<2];

struct node
{
	ll x,y1,y2;
	ll k;
	ll valy1,valy2;
}arr[maxn*2];

bool cmp(node a,node b)
{
	return a.x < b.x;
}

void build(ll now,ll l,ll r)
{
	tree[now].cnt = tree[now].len = 0;
	tree[now].l = l,tree[now].r = r;
	
	if(l == r)
		return ;
	
	ll mid = (l+r)/2;
	
	build(now*2,l,mid);
	build(now*2+1,mid+1,r);
	return ;
}

void push(sgt &now,sgt &lt,sgt &rt)
{
	if(now.cnt > 0)
		now.len = raw[now.r+1] - raw[now.l];
	else
		now.len = lt.len + rt.len;
	return ;
}

void add(ll now,ll l,ll r,ll val)
{
	if(l <= tree[now].l && r >= tree[now].r)
	{
		tree[now].cnt += val;
		push(tree[now],tree[now*2],tree[now*2+1]);
		return ;
	}
	
	ll mid = (tree[now].l + tree[now].r)/2;
	
	if(l <= mid)
		add(now*2,l,r,val);
	if(r >= mid+1)
		add(now*2+1,l,r,val);
	
	push(tree[now],tree[now*2],tree[now*2+1]);
	return ;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
	
	while(cin >> n && n)
	{
		ll ans = 0;
		for(ll i = 1; i < maxn; i++)
		{
			c[i] = 0;
			raw[i] = 0;
		}
		
		ll len = 0;
		vector<ll>ty;
		for(ll i = 1; i <= n; i++)
		{
			cin >> x1[i] >> y1[i] >> x2[i] >> y2[i];
			ty.push_back(y1[i]);
			ty.push_back(y2[i]);
			
			arr[++len].k = 1;
			arr[len].x = x1[i];
			arr[len].y1 = y1[i];
			arr[len].y2 = y2[i];
			
			arr[++len].k = -1;
			arr[len].x = x2[i];
			arr[len].y1 = y1[i];
			arr[len].y2 = y2[i];
			
		}
		sort(ty.begin(),ty.end());
		ty.erase(unique(ty.begin(),ty.end()),ty.end());
		sort(arr+1,arr+1+len,cmp);
		
		for(ll i = 1; i <= len; i++)
		{
			arr[i].valy1 = lower_bound(ty.begin(),ty.end(),arr[i].y1) - ty.begin()+1;
			arr[i].valy2 = lower_bound(ty.begin(),ty.end(),arr[i].y2) - ty.begin()+1;
			raw[ arr[i].valy1 ] = arr[i].y1;
			raw[ arr[i].valy2 ] = arr[i].y2;
		}
		
		build(1,1,ty.size()-1);
		
		for(ll i = 1; i <= len; i++)
		{
			if(i > 1)
				ans += (arr[i].x-arr[i-1].x)*tree[1].len;
			
			ll low = arr[i].valy1,high = arr[i].valy2-1;
			add(1,low,high,arr[i].k);
		}
		
		num++;
		cout  << ans << endl;
	} 
	
    return 0;
}

O(n^2)代码

//#include <bits/stdc++.h>
#include <iostream> 
#include <vector>
#include <algorithm>
#include <iomanip>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef long double ld;
const ll maxn = 1e5+100;

ll n,num,c[maxn];
ld x1[maxn],x2[maxn],y1[maxn],y2[maxn],raw[maxn];

struct node
{
	ld x,y1,y2;
	ll k;
	ll valy1,valy2;
}arr[maxn*2];

bool cmp(node a,node b)
{
	return a.x < b.x;
}

int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(0),cout.tie(0);
	
	while(cin >> n && n)
	{
		ld ans = 0;
		for(ll i = 1; i < maxn; i++)
		{
			c[i] = 0;
			raw[i] = 0;
		}
		
		ll len = 0;
		vector<ld>ty;
		for(ll i = 1; i <= n; i++)
		{
			cin >> x1[i] >> y1[i] >> x2[i] >> y2[i];
			ty.push_back(y1[i]);
			ty.push_back(y2[i]);
			
			arr[++len].k = 1;
			arr[len].x = x1[i];
			arr[len].y1 = y1[i];
			arr[len].y2 = y2[i];
			
			arr[++len].k = -1;
			arr[len].x = x2[i];
			arr[len].y1 = y1[i];
			arr[len].y2 = y2[i];
			
		}
		sort(ty.begin(),ty.end());
		ty.erase(unique(ty.begin(),ty.end()),ty.end());
		sort(arr+1,arr+1+len,cmp);
		
		for(ll i = 1; i <= len; i++)
		{
			arr[i].valy1 = lower_bound(ty.begin(),ty.end(),arr[i].y1) - ty.begin()+1;
			arr[i].valy2 = lower_bound(ty.begin(),ty.end(),arr[i].y2) - ty.begin()+1;
			raw[ arr[i].valy1 ] = arr[i].y1;
			raw[ arr[i].valy2 ] = arr[i].y2;
		}
		
		for(ll i = 1; i <= len; i++)
		{
			if(i > 1)
			{
				ld h = 0;
				for(ll j = 1; j < ty.size(); j++)
				{
					if(c[j] > 0)
						h += (raw[j+1]-raw[j]);
				}
				ans += (arr[i].x - arr[i-1].x)*h;
				
				//cout << "答案 " << h << " " << ans << endl;
			}
			
			ll low = arr[i].valy1,high = arr[i].valy2-1;
			for(ll j = low; j <= high; j++)
			{
				c[j] += arr[i].k;	
			}			
		}
								
		num++;
		cout << "Test case #" << num << endl;
		cout << "Total explored area: " << fixed << setprecision(2) << ans << endl;
		cout << endl;
	} 
	
	
	
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值