蓝桥杯算法训练-比较

蓝桥杯算法题解

题目描述

问题描述

给出一个n长的数列,再进行m次询问,每次询问询问两个区间[L1,R1],[L2,R2],
  询问数列第L2到R2个数字每一个数在数列第L1到R1个数中有多少个数字不大于它。

其中 n, m ≤ \le 1000

题解

如果是暴力做法的话,时间复杂度是 O ( n 2 ∗ m ) O(n^2 * m) O(n2m)

就是对于每一个query中的数字遍历一遍 [ l 1 , r 1 ] [l1, r1] [l1,r1]。但是最后一步可以优化,就是可以在 O ( l o g n ) O(logn) O(logn)的时间复杂度内解决数字个数问题。

解决的办法是什么呢?树状数组or线段树

  • 直接把 [ l 1 , r 1 ] [l1, r1] [l1,r1]中的数组数字a[j]放入到树状数组中进行计数。然后对每一个 [ l 2 , r 2 ] [l2, r2] [l2,r2]中的a[j]求个数就行了。
  • java代码, 时间复杂度 O ( m n l o g ( m a x v ) ) O(mnlog(maxv)) O(mnlog(maxv))其中 m a x v = m a x ( a ) maxv = max(a) maxv=max(a)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * @author: Zekun Fu
 * @date: 2022/10/25 23:21
 * @Description: 蓝桥杯算法训练比较
 * 1000 * 1000 * (l1, r1)中小于x的数字个数是有多少,这个可以O(logn)进行解决。解决的办法是什么呢?树状数组or线段树
 * 	直接把[l1, r1]中的数组放入到树状数组中进行计数。然后对每一个[l2, r2]中的a[j]求个数就行了。
 * 
 */

public class Main{
    private static int maxn = 1005;
    private static int[] c = new int[maxn];
    private static int[] a = new int[maxn];
    private static int n, m;
    private static Scanner sc = new Scanner(System.in);
    private static int lowbit(int x) {
        return x & -x;
    }
    private static void add(int x, int num) {
        for (int i = x; i < maxn; i += lowbit(i)) {
            c[i] += 1;
        }
    }
    private static int sum(int x) {
        int res = 0;
        for (int i = x; i != 0; i -= lowbit(i)) {
            res += c[i];
        }
        return res;
    }
    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt() + 1;
        }
        for (int i = 0; i < m; i++) {
            int a1 = sc.nextInt();
            int b1 = sc.nextInt();
            int a2 = sc.nextInt();
            int b2 = sc.nextInt();
            Arrays.fill(c, 0);
            for (int j = a1 - 1; j < b1; j++) {
                add(a[j], 1);
            }
            for (int j = a2 - 1; j < b2; j++) {
                int x = a[j];
                if (j != b2 - 1)
                    System.out.print(sum(x) + " ");
                else System.out.println(sum(x));
            }
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值