题目:NLO (模拟)

在Žabnik村的当地人多年来一直与UFO进行斗争,UFO在稻田里创造了许多个圆圈,这种行为在夏天割草是尤其明显。

让我们想象一个由n行m列组成的矩形稻田,左上角坐标为(1,1),右下角坐标为(n,m)。每块稻田内都有一定数量的草,最初,所有稻田的草量都等于1,在K天内,圆形UFO每天都降落在地上,在地面盘旋,在第i天一早,半径为Ri的UFO在坐标(xi,yi)的稻田上着陆,收割掉UFO覆盖的稻田上的所有草,换句话说,如果坐标(x,y)在(xi-x)2+(yi-y)2≤Ri2内,那么坐标(x,y)中所有的稻田草量都将变为0。当新的一天到来时,所有稻田的草量都增加1.

在第k天的傍晚,当地人将收割所有的草并存储用来喂牛,问他们能收到多少的草?

输入格式

第一行输入两个数N和M,表示稻田的行数和列数(1≤n,m≤100000)

第二行输入一个数K(1≤K≤100),UFO在当地人收割草前降落的天数。

接下来K行,每行输入三个数字xi,yi,Ri(1<xi<n,1<yi<m,1≤Ri≤min(xi-1,yi-1,n-xi,m-yi)),表示第i天降落的UFO的坐标和半径。

输出格式

答案输出一行,表示当地人最多能收到的草的数量。

样例

样例输入1

6 6
3
4 4 2
3 3 2
2 4 1

样例输出1

68

样例输入2

100 100
2
50 50 49
30 30 29

样例输出2

9534

样例输入3

33333 44444
1
11111 22222 9999

样例输出3

1167355751

思路:
首先这道题不能强行在数组上进行修改,因为无论是空间还是时间都会爆。

我们思考对于每一个圆形,那些点是必须要的,很明显只有圆边上的边我们需要记忆。

接着就考虑两个圆相交的情况,其实也很简单,将这个圆划分成一列一列的就行了。

代码:
 

#include<bits/stdc++.h>
using namespace std;
struct node
{
	long long u;
	long long d;
	long long t;
	node(){}
	node(long long U,long long D,long long T):u(U),d(D),t(T){};
};
long long n,m;
long long k;
long long ans;
vector<node> v[100005];
void update(long long lie,long long u,long long d,long long _index)
{
	for(int i=0,siz=v[lie].size();i<siz;i++)
	{
		if(u<=v[lie][i].u&&v[lie][i].u<=d&&d<v[lie][i].d)
		{
			v[lie].push_back(node(d+1,v[lie][i].d,v[lie][i].t));
			v[lie].erase(v[lie].begin()+i);
			siz--;
			i--;
		}
		else if(v[lie][i].u<u&&d<v[lie][i].d)
		{
			v[lie].push_back(node(v[lie][i].u,u-1,v[lie][i].t));
			v[lie].push_back(node(d+1,v[lie][i].d,v[lie][i].t));
			v[lie].erase(v[lie].begin()+i);
			siz--;
			i--;
		}
		else if(u>v[lie][i].u&&u<=v[lie][i].d&&v[lie][i].d<=d)
		{
			v[lie].push_back(node(v[lie][i].u,u-1,v[lie][i].t));
			v[lie].erase(v[lie].begin()+i);
			siz--;
			i--;
		}
		else if(u<=v[lie][i].u&&v[lie][i].d<=d)
		{
			v[lie].erase(v[lie].begin()+i);
			siz--;
			i--;
		}
	}
	v[lie].push_back(node(u,d,_index));
}
int main()
{
	cin>>n>>m>>k;
	ans=n*m*k;
	for(int i=1;i<=k;i++)
	{
		long long a,b,r;
		cin>>a>>b>>r;
		for(int y=max(1ll,b-r);y<=min(m,b+r);y++)
		{
			long long u;
			long long v;
			u=max((long long)ceil(-sqrt((r+y-b)*(r-y+b))+a),1ll);
			v=min((long long)floor(sqrt((r+y-b)*(r-y+b))+a),n);
			update(y,u,v,i);
		}
	}
	for(int i=1;i<=m;i++)
	{
		for(int j=0;j<v[i].size();j++)
		{
			ans=ans-(v[i][j].d-v[i][j].u+1)*v[i][j].t;
		}
	}
	cout<<ans;
	return 0;
}

 

posted @ 2019-08-23 19:50  loney_s  阅读(156)  评论(0)    收藏  举报