Vijos 1883 月光的魔法 模拟(不用线段树233)

背景

影几欺哄了众生了
天以外——
月儿何曾圆缺

描述

有些东西就如同月光的魔法一般.
Luke是爱着vijos的.
他想为自己心爱的东西画些什么.
就画N个圆吧.
把它们的圆心都固定在x轴上.
圆与圆.
为了爱,两两不能相交.
为了爱,它们可以互相贴在一起.
内切或外切,都是允许的.
vijos的美丽,在于人心.
vijos的孩子们,一定能告诉大家:Luke画的圆究竟把平面分割成了多少块?
月光恬美地洒在大地上.
Luke知道,如果什么都不画,平面就只有一块.多美呢!
Luke知道,只画一个圆,平面就分成了两块.也很美呢!
但Luke还是要多画一些的,因为他真的深爱着vijos呢.

格式

输入格式

输入数据第一行:输出一个整数N,1<=N<=300,000.表示圆的个数.
之后N行,每一行有2个整数,x[i]和r[i]表示圆心固定在x[i]的位置,半径为r[i].
-1,000,000,000<=x[i]<=1,000,000,000
1<=r[i]<=1,000,000,000
所有圆都是唯一的,不会出现重叠.

输出格式

输出只有一行,要求输出平面被分割成了多少块.

样例1

样例输入1

2
1 3
5 1

样例输出1

3

样例2

样例输入2

3
2 2
1 1
3 1

样例输出2

5

样例3

样例输入3

4
7 5
-9 11
11 9
0 20

样例输出3

6

限制

对于40%的数据:
N<=5000.
对于100%的数据:
1<=N<=300,000;-1,000,000,000<=x[i]<=1,000,000,000;1<=r[i]<=1,000,000,000
 

题解:

乍一看,我们可能会觉得这是一个线段树的题,但我们发现,其实它只要最后的结果,所以我们用不着线段树,我们可以模拟!!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int vis[1300030];
struct qer
{
	int l, r, len;
}d[1300030];
struct lsh
{
	int num, id;
}ls[1600030];
struct sss
{
	int vi, l, r;
}used[1300030];
bool cmp(lsh a, lsh b)
{
	return a.num < b.num;
}
bool cmmp(qer a, qer b)
{
	return a.len < b.len;
}
int main()
{
	int n;
	cin >> n;
	ls[0].num = -2147483600;
	for (int i = 1; i <= n; i++)
	{
		int x, r;
		scanf("%d%d", &x, &r);
		ls[i*2-1].num = x-r;
		ls[i*2].num = x+r;
		ls[i*2-1].id = i;
		ls[i*2].id = i;
	}
	sort(ls+1, ls+n*2+1, cmp);
	int cnt = 0;
	for (int i = 1; i <= n*2; i++)
	{
		vis[ls[i].id]++;
		if (ls[i].num - ls[i-1].num == 1)
			cnt++;
		if (ls[i].num - ls[i-1].num > 1)
			cnt+=2;
		if (vis[ls[i].id] == 1)
			d[ls[i].id].l = cnt;
		else
			d[ls[i].id].r = cnt, d[ls[i].id].len = d[ls[i].id].r - d[ls[i].id].l + 1;
	}
	sort(d+1, d+n+1, cmmp);
	int ans = 1;
	for (int i = 1; i <= n; i++)
	{
		int j = d[i].l;
		bool flag = 0;
		while (j <= d[i].r)
		{
			if (!used[j].vi)
			{
				flag = 1;
				used[j].vi = 1;
				used[j].l = d[i].l;
				used[j].r = d[i].r;
			}
			else
			{
				if (used[j].r == d[i].r && !flag)
					ans+=2;
				j = used[j].r;
			}
			j++;
		}
		if (flag)
			ans++;
	}
	cout << ans;
	return 0;
}

 

上一篇
下一篇