1 条题解

  • 0
    @ 2025-8-24 21:41:31

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 浮尘ii
    **

    搬运于2025-08-24 21:41:31,当前版本为作者最后更新于2017-01-02 22:26:19,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    笔者的做法和下面几篇题解是一样的,在这里就不重复叙述了。这里介绍一下官方给出的做法。

    ##题目分析

    把平面上每一个区域看作一个结点,最外层没有边界的区域也看作一个结点。如果一个区域刚好被另外一个区域直接包含,则连边。构成的图上做最短路径即可以得到40~60的分数。

    又发现,上述得到的图是树结构的,在树上预处理好任意两点的最近公共祖先,之后的询问可以线形完成,这便可以得到满分。

    ##std

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    struct Point
    {
        ll x,y;
        Point(){}
        Point(ll _x,ll _y):x(_x),y(_y){}
        Point operator - (const Point &t)const
        {
            return Point(x-t.x,y-t.y);
        }
        ll len2()
        {
            return x*x+y*y;
        }
    };
    struct Circle
    {
        Point o;
        ll r;
        Circle(){}
        Circle(Point _o,ll _r):o(_o),r(_r){}
        bool operator < (const Circle &t)const
        {
            return r<t.r;
        }
        bool contain(Point t)
        {
            return (t-o).len2()<r*r;
        }
    }c[8005];
    struct Edge
    {
        int to,nxt;
    }edge[8005];
    int head[8005],tot;
    void init()
    {
        memset(head,-1,sizeof(head));
        tot=0;
    }
    void addedge(int u,int v)
    {
        edge[tot].to=v;
        edge[tot].nxt=head[u];
        head[u]=tot++;
    }
    int fa[8005],dep[8005];
    void dfs(int u,int la)
    {
        fa[u]=la;
        dep[u]=(la>=0 ? dep[la]+1 : 0);
        for(int i=head[u];~i;i=edge[i].nxt)
            dfs(edge[i].to,u);
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%lld%lld%lld",&c[i].o.x,&c[i].o.y,&c[i].r);
        c[n++]=Circle(Point(0,0),200000000);
        sort(c,c+n);
        init();
        for(int i=0;i<n-1;i++)
            for(int j=i+1;j<n;j++)
                if(c[j].contain(c[i].o))
                {
                    addedge(j,i);
                    break;
                }
        dfs(n-1,-1);
        int m;
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int u[2];
            for(int j=0;j<2;j++)
            {
                Point p;
                scanf("%lld%lld",&p.x,&p.y);
                for(int k=0;k<n;k++)
                    if(c[k].contain(p))
                    {
                        u[j]=k;
                        break;
                    }
            }
            int res=0;
            while(u[0]!=u[1])
            {
                if(dep[u[0]]>dep[u[1]])u[0]=fa[u[0]];
                else u[1]=fa[u[1]];
                res++;
            }
            printf("%d\n",res);
        }
        return 0;
    }
    

    ##吐槽

    这玩意又难写,常数又大(原题时限5s),不知道出题人怎么想到的。

    • 1

    信息

    ID
    1807
    时间
    3000ms
    内存
    125MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者