• speike


    speike

    题目描述

    众所周知,Speike 狗是一条特别喜欢追着Tom 打的狗。

    现在,Tom 又把Speike 惹生气了,现在Speike 需要跨越千山万水找Tom 报仇。

    Speike 所在的世界可以看成是一个无穷大的平面,平面由一个平面直角坐标系确定。在平面上有许多不相交的矩形障碍,矩形的四边平行于坐标轴。

    Speike 需要从 (0,0)(0,0) 出发,在尽量短的时间内跑到 (X_t,0)(Xt,0),也就是Tom 在的位置。

    出题人规定,Speike 只能沿着平行于坐标轴的方向运动,且不能进入矩形障碍的内部,但是可以在障碍边界上移动。

    所有障碍的横坐标都在 [0,X_t][0,Xt] 之内。保证矩形不相交(即没有公共面积),也不会退化成线段或者点。

    Speike 的智商不是很高,因此他需要你帮忙设计一条最短的路线。当然,你只需要告诉他路线的长度就行了。

    输入格式

    第一行一个整数 nn,代表障碍的个数。

    第二行一个整数 X_tXt,代表终点的横坐标。

    第三行开始,共 nn 行,每行4 个整数 a,b,c,da,b,c,d,代表每个矩形的某两个相对的顶点的坐标为 (a,b)(a,b) 和 (c,d)(c,d)

    输出格式

    共一行,一个整数,代表最短路线的长度。

    样例

    共下发三个样例,分别与第2; 4; 11 号测试点的数据范围与特性一致。

    数据范围与提示

    测试点编号n的范围特殊性质
    1 n le 0n0
    2,3 n le 1n1
    4,5,6 n le 20n20 a, b, c, d, X_{t} inleft[-10^{3}, 10^{3} ight]a,b,c,d,Xt[103,103]
    7,8,9,10 n le 200n200 a, b, c, d, X_{t} inleft[-10^{5}, 10^{5} ight]a,b,c,d,Xt[105,105]
    11,12,13 n le 2000n2000 a, b, c, d, X_{t} inleft[-10^{3}, 10^{3} ight]a,b,c,d,Xt[103,103]
    14,15 n le 2000n2000
    16,17 n le 10^5n105 所有矩形都与xx轴相交
    18,19,20 n le 5 imes 10^5n5×105 nn有一定梯度

    -10^{8} leq a, c leq X_{t} leq 10^{8},-10^{8} leq b, d leq 10^{8}, n inleft[0,10^{5} ight]108a,cXt108,108b,d108,n[0,105]。
    保证矩形不相交(即没有公共面积),每个矩形不会退化成线段或者点,且横坐标都在 [0,X_t][0,Xt] 之内。

    来源

    CSP-S 2019模拟 长沙一中2


    Solution
    我就把题解的话复读一边:
    考虑一条路线,x一定是单调增的。
    而且该路线一定贴着矩形的边。
    那么我们可以把矩形按左边的线排序,对于每一个矩形考虑他的左边两个端点,找到最近一个可以转移的矩形转移就行。
    找矩形可以线段树或者set
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 1000006
    #define lb(x) lower_bound(Y+1,Y+m+1,x)-Y
    #define mid ((l+r)>>1)
    #define ls k<<1
    #define rs k<<1|1
    using namespace std;
    int n,ed,Y[maxn],f[maxn][2],t;
    int tr[maxn*4];
    struct node{
        int a,b,c,d;
    }s[maxn];
    bool cmp(node A,node B){
        return A.a<B.a;
    }
    void add(int k,int l,int r,int li,int ri,int v){
        if(l>=li&&r<=ri){tr[k]=v;return;}
        if(li<=mid)add(ls,l,mid,li,ri,v);
        if(ri>mid)add(rs,mid+1,r,li,ri,v);
    }
    void ask(int k,int l,int r,int pl){
        t=max(t,tr[k]);
        if(l==r)return;
        if(pl<=mid)return ask(ls,l,mid,pl);
        return ask(rs,mid+1,r,pl);
    }
    int main(){
        cin>>n>>ed;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d%d",&s[i].a,&s[i].b,&s[i].c,&s[i].d);
            if(s[i].a>s[i].c)swap(s[i].a,s[i].c);
            if(s[i].b>s[i].d)swap(s[i].b,s[i].d);
            Y[i]=s[i].d,Y[i+n]=s[i].b;
        }
        
        int N=n+n+1;Y[N]=0;
        sort(Y+1,Y+N+1);int m=unique(Y+1,Y+N+1)-Y-1;
        s[++n]=(node){ed,0,ed,0};
        sort(s+1,s+n+1,cmp);
        for(int i=1;i<=n;i++){
            t=0;ask(1,1,m,lb(s[i].b));
            f[i][0]=min(f[t][0]+abs(s[t].b-s[i].b),f[t][1]+abs(s[t].d-s[i].b));
            t=0;ask(1,1,m,lb(s[i].d));
            f[i][1]=min(f[t][0]+abs(s[t].b-s[i].d),f[t][1]+abs(s[t].d-s[i].d));
            add(1,1,m,lb(s[i].b),lb(s[i].d),i);
        }
        cout<<f[n][0]+ed<<endl;
        return 0;
    }
    View Code
     
  • 相关阅读:
    topcoder srm 320 div1
    topcoder srm 325 div1
    topcoder srm 330 div1
    topcoder srm 335 div1
    topcoder srm 340 div1
    topcoder srm 300 div1
    topcoder srm 305 div1
    topcoder srm 310 div1
    topcoder srm 315 div1
    如何统计iOS产品不同渠道的下载量?
  • 原文地址:https://www.cnblogs.com/liankewei/p/11850192.html
Copyright © 2020-2023  润新知