[COCI2018-2019#3] NLO
原题链接
考虑最后的麦田图形,可以发现,如果一个格子最后一次被飞碟降落是在第
可以知道每个圆对一行的影响是一段区间,因此对每一行分别处理。
对于每一行,从后面的圆开始考虑,一次次将该圆的区间覆盖,统计本次新覆盖了多少个点,使答案加上点数乘以本次的权值,即
显然可以将每行要操作的区间边界离散化从而加速考虑区间。
时间复杂度
由于
如果手写 bitset 来进行每一次的区间统计和修改操作,则可以将时间复杂度优化到
空间复杂度
Code
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define pow(x) ((x)*(x))
#define mset(arr,val) memset(arr,val,sizeof(arr))
using namespace std;
const int SIZE=2e2+10,EXTRA=1e5+10;
typedef long long ll;
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=(x*10)+(ch^48),ch=getchar();
return x;
}
int n,m,k,X[SIZE],Y[SIZE],R[SIZE],bin[SIZE],trans[EXTRA],s[SIZE],t[SIZE],top;
ll ans;
bool use[SIZE];
int main()
{
n=read(),m=read(),k=read();
for(int i=1;i<=k;i++)X[i]=read(),Y[i]=read(),R[i]=read();
for(int l=1,uniq;l<=n;l++)
{
mset(bin,0),top=0,mset(use,0),s[0]=0,t[0]=m,bin[++top]=s[0],bin[++top]=t[0];
for(int i=1,len;i<=k;i++)
{
if(R[i]<abs(X[i]-l))continue;
len=sqrt(pow(R[i])-pow(X[i]-l)),s[i]=Y[i]-len-1,t[i]=Y[i]+len,bin[++top]=s[i],bin[++top]=t[i];
}
sort(bin+1,bin+top+1),uniq=unique(bin+1,bin+top+1)-bin-1;
for(int i=1;i<=uniq;i++)trans[bin[i]]=i;
for(int i=0,ts,tt;i<=k;i++)ts=trans[s[i]],tt=trans[t[i]],s[i]=ts,t[i]=tt;
int res;
for(int i=k;i;i--)
{
if(R[i]<abs(X[i]-l))continue;
res=0;
for(int j=s[i]+1;j<=t[i];j++)if(!use[j])res+=bin[j]-bin[j-1],use[j]=true;
ans+=(k-i)*res;
}
res=0;
for(int j=2;j<=uniq;j++)if(!use[j])res+=bin[j]-bin[j-1];
ans+=k*res;
}
printf("%lld",ans);
return 0;
}