1 条题解

  • 0
    @ 2025-8-24 22:28:43

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar FQ04gty
    Let me be cruel, not unnatural.

    搬运于2025-08-24 22:28:43,当前版本为作者最后更新于2022-09-27 11:44:24,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    原题链接

    考虑最后的麦田图形,可以发现,如果一个格子最后一次被飞碟降落是在第 ii 天,那么最后的数字是 kik-i

    可以知道每个圆对一行的影响是一段区间,因此对每一行分别处理。

    对于每一行,从后面的圆开始考虑,一次次将该圆的区间覆盖,统计本次新覆盖了多少个点,使答案加上点数乘以本次的权值,即 kik-i,再将区间覆盖。最后再统计没有被覆盖的点数量乘上 kk

    显然可以将每行要操作的区间边界离散化从而加速考虑区间。

    时间复杂度 O(nk2)O(nk^2)。但是由于不是每一次都会完整覆盖每一行,所以跑不满。

    由于 kk 很小,这里采用 log\log 级别的数据结构优化可能不会快多少。

    如果手写 bitset 来进行每一次的区间统计和修改操作,则可以将时间复杂度优化到 O(nk2w)O(\frac{nk^2}{w})

    空间复杂度 O(n)O(n)

    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;
    }
    
    • 1

    信息

    ID
    6429
    时间
    3000ms
    内存
    64MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者