【卡常】2284 - NLO

题目链接<http://acm.zjnu.edu.cn/CLanguage/showproblem?problem_id=2284>


题意:

在一个n*m的矩形中,每次会长长度为1的草。有k个UFO降临,会把严格在圆形范围内的草割光。问最后地面上还剩多少的草。

1<=n,m<=1e5,1<=k<=100


题解:

对于圆的面积,只能考虑每一行被覆盖的长度,然后累加。

这样,对于每一行,把每个UFO拆成左右两个点,记录点的位置,是左端点还是右端点,是第几个UFO。

把这一行的点丢进优先队列(不能用set,这样会tle)(不能开n个队列,这样会mle)。然后从左到右扫一遍队列,再开一个set维护最后面来的UFO,并计算答案。


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+7;
struct Node{
    int p,f,id;
    bool operator<(const Node k)const{
        return p==k.p?id<k.id:p>k.p;
    }
};
priority_queue<Node>q;
set<int,greater<int> >st;
int y[N],x[N],r[N];
int main(){
    int n,m,k;
    scanf("%d%d",&n,&m);
    scanf("%d",&k);
    for(int i=1;i<=k;i++){
        scanf("%d%d%d",&y[i],&x[i],&r[i]);
    }
    ll ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=k;j++){
            int lo=y[j]-r[j];
            int hi=y[j]+r[j];
            if(hi<i||lo>i) continue;
            int tt=(int)floor(sqrt(1ll*r[j]*r[j]-1ll*(i-y[j])*(i-y[j])));
            q.push((Node){x[j]-tt,1,j});
            q.push((Node){x[j]+tt+1,-1,j});
        }
        int tmp=1;
        while(!q.empty()){
            Node t=q.top();q.pop();
            if(t.f==1){
                if(st.empty()){
                    ans+=1ll*(t.p-tmp)*k;
                    tmp=t.p;
                }
                else if(t.id>*st.begin()){
                    ans+=1ll*(t.p-tmp)*(k-*st.begin());
                    tmp=t.p;
                }
                st.insert(t.id);
            }
            else{
                if(*st.begin()==t.id){
                    ans+=1ll*(t.p-tmp)*(k-*st.begin());
                    tmp=t.p;
                }
                st.erase(t.id);
            }
        }
        ans+=1ll*(m-tmp+1)*k;
    }
    printf("%lld\n",ans);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值