【JZOJ5234】外星人的路径

本文介绍了一种解决外星人操控路径问题的算法。该算法通过预先对关键点进行排序,然后使用二分查找来快速确定每个指令后的下一个位置。时间复杂度为O((n+m)log2n),适用于大量关键点的场景。

description

有一个外星人控制了你的大脑。一开始你处于原点(0,0)。外星人有一个由(R,U,D,L)组成的长度为M 的操作序列,分别代表(右,上,下,左)。
平面上有N 个关键点,每当外星人给出一个操作,你需要在这个方向上找到最近的一个关键点,并走到那个点上。保证输入数据合法。
在这里插入图片描述

上图为第三个样例的图示。


analysis

  • 思路比较好想,虽说nnn很大,但是我们可以先排个序

  • a,ba,ba,b分别快排一次,aaa按横坐标升序排序,bbb则相反

  • 如果为向上或向下,那么在aaa里二分找出当前点(快排前把(0,0)(0,0)(0,0)也丢进去)

  • 找出当前点nownownow后,若为upupup,下一个点即为a[now+1]a[now+1]a[now+1]

  • downdowndown,下一个点即为a[now−1]a[now-1]a[now1]

  • 题目保证数据合法,可以免了判断

  • 左右就在bbb里二分找当前点,同理

  • 时间复杂度O((n+m)log2n)O((n+m)log_2n)O((n+m)log2n)


code

var
        a,b:array[0..100000,0..2]of longint;
        n,m,i,j,l,r,mid,nowx,nowy:longint;
        ch:char;
procedure qsort1(l,r:longint);
var
        i,j,mid,mid1:longint;
begin
        i:=l;
        j:=r;
        mid:=a[(l+r)shr 1,1];
        mid1:=a[(l+r)shr 1,2];
        repeat
                while (a[i,1]<mid)or(a[i,1]=mid)and(a[i,2]<mid1)do inc(i);
                while (a[j,1]>mid)or(a[j,1]=mid)and(a[j,2]>mid1)do dec(j);
                if i<=j then
                begin
                        a[0]:=a[i];
                        a[i]:=a[j];
                        a[j]:=a[0];
                        inc(i);
                        dec(j);
                end;
        until i>j;
        if l<j then qsort1(l,j);
        if i<r then qsort1(i,r);
end;
procedure qsort2(l,r:longint);
var
        i,j,mid,mid1:longint;
begin
        i:=l;
        j:=r;
        mid:=b[(l+r)shr 1,2];
        mid1:=b[(l+r)shr 1,1];
        repeat
                while (b[i,2]<mid)or(b[i,2]=mid)and(b[i,1]<mid1)do inc(i);
                while (b[j,2]>mid)or(b[j,2]=mid)and(b[j,1]>mid1)do dec(j);
                if i<=j then
                begin
                        b[0]:=b[i];
                        b[i]:=b[j];
                        b[j]:=b[0];
                        inc(i);
                        dec(j);
                end;
        until i>j;
        if l<j then qsort2(l,j);
        if i<r then qsort2(i,r);
end;
begin
        assign(input,'tratincice.in');reset(input);
        assign(output,'tratincice.out');rewrite(output);
        readln(n,m);
        for i:=1 to n do
        begin
                for j:=1 to 2 do
                begin
                        read(a[i,j]);
                        b[i,j]:=a[i,j];
                end;
                readln;
        end;
        qsort1(1,n);
        qsort2(1,n);
        for i:=1 to m do
        begin
                read(ch);
                if ch in['U','D'] then
                begin
                        l:=1;
                        r:=n;
                        while l<=r do
                        begin
                                mid:=(l+r)shr 1;
                                if (a[mid,1]>nowx)or(a[mid,1]=nowx)and(a[mid,2]>nowy)then
                                        r:=mid-1
                                else l:=mid+1;
                        end;
                        if ch='U' then
                        begin
                                nowx:=a[r+1,1];
                                nowy:=a[r+1,2];
                        end
                        else
                        begin
                                nowx:=a[r-1,1];
                                nowy:=a[r-1,2];
                        end;
                end
                else
                begin
                        l:=1;
                        r:=n;
                        while l<=r do
                        begin
                                mid:=(l+r)shr 1;
                                if (b[mid,2]>nowy)or(b[mid,2]=nowy)and(b[mid,1]>nowx)then
                                        r:=mid-1
                                else l:=mid+1;
                        end;
                        if ch='R' then
                        begin
                                nowx:=b[r+1,1];
                                nowy:=b[r+1,2];
                        end
                        else
                        begin
                                nowx:=b[r-1,1];
                                nowy:=b[r-1,2];
                        end;
                end;
        end;
        writeln(nowx,' ',nowy);
        close(input);close(output);
end.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值