题解 | #E 希尔伯特排序#

Hilbert Sort

https://ac.nowcoder.com/acm/contest/80186/E

E 希尔伯特排序


该问题的主要核心是如何比较两个坐标的前后关系

首先, 对于k阶曲线, 它的大小是2^k * 2^k, 可以分为大小为2^(k-1) * 2^(k-1)的四个区块: 左上1, 左下2, 右下3, 右上4(标号按行走顺序)

给定一个点坐标,求它在哪个区块是非常好求的, 只需要判断x,y和2^(k-1)大小即可

  • 如果两个点所属区块不同, 那么直接比较区块的先后即可

  • 如果所属区块相同, 那么我们可以做降阶处理

    因为两个点属于同一区块, 另外的三个区块是不需要的, 降阶就找到了一个规模为k-1的子问题, 可以递归再次判断区块先后来比较顺序

如何进行降阶(坐标变换): alt alt alt alt

import java.util.Arrays;
import java.util.Scanner;

public class Main {

    static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        int n = sc.nextInt();
        int k = sc.nextInt();
        long[][] A = new long[n][2];
        for (int i = 0; i < n; i++) {
            A[i][0] = sc.nextLong();
            A[i][1] = sc.nextLong();
        }
        Arrays.sort(A, ((o1, o2) -> compare(o1, o2, k)));
        for (long[] a : A) {
            System.out.println(a[0] + " " + a[1]);
        }
    }

    /**
     k阶情况下点a和点b的前后关系

     @param a,b 点坐标[x,y], x为行轴(竖向),y为列轴(横向)
     @param k   曲线阶数
     @return -1:a在b前; 1:a在b后; 0:a=b
     */
    static int compare(long[] a, long[] b, int k) {
        // ab相同
        if (a[0] == b[0] && a[1] == b[1]) return 0;
        // ab不同
        int id1 = get(a, k), id2 = get(b, k);// 将k阶曲线分成四个区块(左上1,左下2,右下3,右上4)
        // 区块不同, 比较区块前后关系即可
        if (id1 != id2) return id1 - id2;
        // 区块相同,递归比较
        if (id1 == 1) { // 第一区块
            long[] na = new long[]{a[1], a[0]};// 看示例图, 从第k-1阶到k阶第一区块有一个转置
            long[] nb = new long[]{b[1], b[0]};
            return compare(na, nb, k - 1);
        }
        long half = 1L << (k - 1);
        if (id1 == 2) {// 第二区块
            long[] na = new long[]{a[0] - half, a[1]}; // 无转置, 将行坐标移到第一区块上即可
            long[] nb = new long[]{b[0] - half, b[1]};
            return compare(na, nb, k - 1);
        }
        if (id1 == 3) {// 第三区块
            long[] na = new long[]{a[0] - half, a[1] - half};// 无转置, 行列均移到第一区块上即可
            long[] nb = new long[]{b[0] - half, b[1] - half};
            return compare(na, nb, k - 1);
        }
        // 第四区块
        // 比较特殊, 它和第一区块是镜像的结构, 这里我把k阶终点映射做k-1阶的起点
        // 以右上角为原点, 向左的方向代替原x轴, 那么原x坐标就变为了现在的y坐标
        // 向下的方向代替原y轴, 现在的x坐标 = 右上角到当前y坐标的距离 = 2 * half - y + 1
        long[] na = new long[]{2 * half - a[1] + 1, a[0]};
        long[] nb = new long[]{2 * half - b[1] + 1, b[0]};
        return -compare(na, nb, k - 1);
    }


    static int get(long[] a, int k) {
        long half = 1L << (k - 1);
        long x = a[0], y = a[1];
        if (x <= half) {
            if (y <= half) {
                return 1;// 左上
            } else {
                return 4;// 右上
            }
        } else {
            if (y <= half) {
                return 2;// 左下
            } else {
                return 3;// 右下
            }
        }
    }
}

全部评论

相关推荐

joecii:如果没有工资,那可能没有工资是这家公司最小的问题了
找实习记录
点赞 评论 收藏
分享
最终还是婉拒了小红书的offer,厚着脸皮回了字节。其实这次字节不管是组内的氛围、HR的沟通体验,都比之前好太多,开的薪资也还算过得去,这些都是让我下定决心的原因之一。但最核心的,还是抵不住对Agent的兴趣,选择了Ai&nbsp;Coding这么一个方向。因为很多大佬讲过,在未来比较火的还是属于那些更加垂类的Agent,而Ai&nbsp;Coding恰好是Coding&nbsp;Agent这么一个领域,本质上还是程序员群体和泛程序员群体这个圈子的。目前也已经在提前实习,也是全栈这么一个岗位。就像最近阿里P10针对前端后端等等不再那么区分,确实在Agent方向不太区分这个。尤其是我们自己做AI&nbsp;Coding的内容,基本上90%左右的内容都是AI生成的,AI代码仓库贡献率也是我们的指标之一。有人说他不好用,那肯定是用的姿态不太对。基本上用对Skill、Rules&nbsp;加上比较好的大模型基本都能Cover你的大部分需求,更别说Claude、Cursor这种目前看来Top水准的Coding工具了(叠甲:起码在我看来是这样)。所以不太区分的主要原因,还是针对一些例如Claude&nbsp;Code、Cursor、Trae、Codex、CC等一大堆,他们有很多新的概念和架构提出,我们往往需要快速验证(MVP版本)来看效果。而全栈就是这么快速验证的一个手段,加上Ai&nbsp;Coding的辅助,目前看起来问题不大(仅仅针对Agent而言)。而且Coding的产品形态往往是一个Plugin、Cli之类的,本质还是属于大前端领域。不过针对业务后端来看,区分还是有必要的。大家很多人也说Agent不就是Prompt提示词工程么?是的没错,本质上还是提示词。不过现在也衍生出一个新的Context&nbsp;Eneering,抽象成一种架构思想(类比框架、或者你们业务架构,参考商品有商品发布架构来提效)。本质还是提示词,但是就是能否最大化利用整个上下文窗口来提升效果,这个还是有很多探索空间和玩法的,例如Cursor的思想:上下文万物皆文件,&nbsp;CoWork之类的。后续也有一些Ralph&nbsp;Loop啥的,还有Coding里面的Coding&nbsp;Act姿态。这种才是比较核心的点,而不是你让AI生成的那提示词,然后调用了一下大模型那么简单;也不是dify、LangGraph搭建了一套workflow,从一个node走到另外一个node那么简单。Agent和WorkFLow还是两回事,大部分人也没能很好的区分这一点。不过很多人说AI泡沫啥啥啥的,我们ld也常把这句话挂在嘴边:“说AI泡沫还是太大了”诸如此类。我觉得在AI的时代,懂一点还是会好一点,所以润去字节了。目前的实习生活呢,除了修一些Tools的问题,还包括对比Claude、Cursor、Trae在某些源码实现思想上的点,看看能不能迁移过来,感觉还是比较有意思。不过目前组内还是主要Follow比较多,希望下一个阶段就做一些更有创新的事情哈哈。这就是一个牛马大学生的最终牧场,希望能好好的吧。说不定下次发的时候,正式AI泡沫结束,然后我又回归传统后端这么一个结局了。欢迎交流👏,有不对的🙅不要骂博主(浅薄的认知),可以私聊交流
码农索隆:和优秀的人,做有挑战的事
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务