题意
给你一个网格点,在点上画几个圆问网格点剩下的点有几个
题解
把网格的每一行看作扫描线,扫描整个网格,对于每个圆在每一行有左右两点的坐标,求出来放在vetctor中,最后将每行的vector排序,先对起点排序对与起点相同的点对终点排序,然后遍历每个vt,记录前一个的终点坐标
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAXN=22222;
vector<pair<int,int>> vt[MAXN];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
for(int i=0;i<MAXN;i++)
vt[i].clear();
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
for(int i1=0;i1<q;i1++)
{
int x,y,r;
scanf("%d%d%d",&x,&y,&r);
for(int i=0;i<n;i++)
{
int up=max(0,x-r);
int dn=min(n-1,x+r);
if(i<up||i>dn) continue;
int k1=floor(sqrt(r*r-abs(x-i)*abs(x-i)));
int z1=max(0,y-k1);
int z2=min(m-1,y+k1);
vt[i].push_back(make_pair(z1,z2));
}
}
int ans=0;
for(int i=0;i<n;i++)
{
int k=-1;
if(vt[i].size())
{
sort(vt[i].begin(),vt[i].end());
for(auto j:vt[i])
{
if(j.first>k)
ans+=j.second-j.first+1;
else
{
if(j.second>k)
ans+=j.second-k;//注意这里不是j.second-k+1
}
k=max(k,j.second);
}
}
}
printf("%d\n",n*m-ans);
}
return 0;
}