蓝桥杯2024年真题java B组 【H.拼十字】

蓝桥杯2024年真题java B组 【H.拼十字】

原题链接:拼十字

思路:

使用树状数组或线段树解决。

先将输入的信息存入到一个n行3列的数组中,将信息排序,按照长度小到大,长相同时,宽度小到大

排序。

建立三个树状数组,维护三种颜色对应的信息,树状数组的索引就是数据的宽度,值就是有几个这样宽度的数据。

遍历数组每组数据:

当颜色为0时,假设该组数据为6 3 0,则要求的就是其他两个颜色中宽度比当前宽度大的(因为长度已经从小到大排过序),也就是去1,2树状数组中找宽度比当前3的宽度大的,就是下标大于3的(就是宽度大于三的),就是1,2树状数组中的4到无穷大(就是到N)的和。

将该组数据加到对应的树状数组0中去,就是tree0.add(arr[i][1],1)

其他两种情况同理。

该过程中的树状数组中的很多空间是无效的,但还是通过了。

code:

java 复制代码
import java.io.*;
import java.util.Arrays;
public class Main {
    static int N = 100005;
    static int MOD = 1000000007;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StreamTokenizer in = new StreamTokenizer(br);
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        in.nextToken();
        int n = (int) in.nval;
        //数据信息,一行存储一个数据项
        int[][] arr = new int[n + 1][3];
        Tree tree0 = new Tree(N);
        Tree tree1 = new Tree(N);
        Tree tree2 = new Tree(N);
        for (int i = 1; i <= n; i++) {
            in.nextToken();
            arr[i][0] = (int) in.nval;
            in.nextToken();
            arr[i][1] = (int) in.nval;
            in.nextToken();
            arr[i][2] = (int) in.nval;
        }
        long res = 0;
        //排序,先按照长度升序排序,在按照宽度进行升序排序
        Arrays.sort(arr, (a, b) -> {
            if (a[0] != b[0]) {
                return Integer.compare(a[0], b[0]); // 按 arr[i][0] 升序
            }
            return Integer.compare(a[1], b[1]); // 如果 arr[i][0] 相同,按 arr[i][1] 升序
        });
        for (int i = 1; i <= n; i++) {
            //将当前的节点加入线段树中
            //先求和
            res %= MOD;
            if (arr[i][2] == 0){
                res += tree1.sum(arr[i][1]);
                res += tree2.sum(arr[i][1]);
                tree0.add(arr[i][1],1);
            } else if (arr[i][2] == 1) {
                res += tree0.sum(arr[i][1]);
                res += tree2.sum(arr[i][1]);
                tree1.add(arr[i][1],1);
            }else{
                res += tree0.sum(arr[i][1]);
                res += tree1.sum(arr[i][1]);
                tree2.add(arr[i][1],1);
            }
        }
        out.print(res);
        out.flush();
        out.close();
        br.close();
    }
}
class Tree{
    long[] tree;
    int N;
    public Tree(int N){
        this.N = N;
        tree = new long[N + 1];
    }
    //获取最右边的1
    public long lowBit(int i) {
        return i & -i;
    }
    public void add(int i,long  val) {
        while (i <= N) {
            tree[i] += val;
            i += lowBit(i);
        }
    }
    //计算的是原数组中的 1-i 对应的和
    public long query(int i) {
        long res = 0;
        while (i > 0) {
            res += tree[i];
            i -= lowBit(i);
        }
        return res;
    }
    public long sum(int i){
        return query(N) - query(i);
    }
}
相关推荐
地平线开发者7 小时前
J6B vio scenario sample
算法
Flittly14 小时前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了14 小时前
Java 生成二维码解决方案
java·后端
BothSavage18 小时前
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
算法
小林ixn19 小时前
从暴力到KMP:一道题彻底搞懂字符串匹配的前世今生
算法
人活一口气19 小时前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
烬羽20 小时前
字符串算法入门:从反转字符串到回文判断,面试不再慌
算法·面试
NE_STOP20 小时前
Vibe Coding -- 完整项目案例实操
java
荣码21 小时前
GraphRAG:普通RAG只能回答"点"的问题,我踩了4个坑才搞懂
java·python