递增三元组(二分法)第九届蓝桥杯省赛C++B组真题

算法分析

这题给出的数据范围是是10的5次方量级,因此应选择O(nlogn)或O(n*n)的算法,说明最多只能有一层循环,剩余时间复杂度用于判断和计数。
常规思路很容易想到二分法,二分法能够找到边界,且由于二分法的时间复杂度为O(logn),乘上循环所需要的O(n),刚好满足时间复杂度要求。
有个值得注意的地方是,若选择循环A数组,那么B数组元素的选择会影响到C数组元素的选择,脱离了乘法的独立性,就不能使用乘法来统计方案个数了。因此我们选择循环B数组,这样就能够在循环B数组时,使A的选择不影响C的选择,满足乘法的独立性。

在这里插入图片描述

模板二分法

首先递增排序(必须选择小于等于O(nlogn)的排序方法!),再找到每次循环B数组元素时满足条件的A数组的左边界,满足条件的C数组的右边界,通过边界范围内的个数相乘即得到每次选择不同B数组元素时的方案总数,循环累加即可。

C++ 代码
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 100010;

int n, A[N], B[N], C[N];
long long res; 
//注意空间数据范围,最坏情况下有N的三次方个方案,当N取最大时,数据会达到10的十五次方,爆出int范围

int main ()
{
    cin >> n;
    for(int i=1; i<=n; i++) cin >> A[i];
    for(int i=1; i<=n; i++) cin >> B[i];
    for(int i=1; i<=n; i++) cin >> C[i];
    
    sort(A+1, A+n+1);
    sort(B+1, B+n+1);
    sort(C+1, C+n+1);
    //快速排序O(nlogn)不怎么影响整体时间效率
    
    for(int i=1; i<=n; i++) //循环B数组
    {
        int l = 1, r = n;
        while(l < r) //标准y总左边界二分模板
        {
            int mid = l + r >> 1;
            if(A[mid] >= B[i]) r = mid;
            else l = mid + 1;
        }
        if(A[l] >= B[i]) l--; //特判,若不满足条件,则将下标左移
        int t1 = l; // 保存A数组的下标
        
        l = 1, r = n;
        while(l < r) //标准y总右边界二分模板
        {
            int mid = l + r + 1 >> 1;
            if(B[i] >= C[mid]) l = mid;
            else r = mid - 1;
        }
        if(C[l] <= B[i]) l++; //特判,若不满足条件,则将下标右移
        int t2 = l; //保存C数组的下标
        
        res += (long long)t1 * (n - t2 + 1); //乘法原理
    }
    
    printf("%lld\n", res);
    
    return 0;
}
目前尚未有2024年第十四届蓝桥杯软件C/C++大学B真题与题解发布,因为该事的时间线可能还未到达公布阶段[^1]。然而,可以基于以往的比形式和内容推测其考察的知识点范围以及提供一些常见的练习方向。 以下是关于如何准备此类比的一些指导: ### 准备指南 #### 一、熟悉基础算法 掌握基本的数据结构和经典算法对于参者至关重要。这包括但不限于数、链表、栈、队列等数据结构的应用;排序(快速排序、归并排序)、查找(二分法)、动态规划等问题解决方法的学习与实践。 ```cpp // 快速排序实现 (C++) void quickSort(int arr[], int low, int high){ if(low < high){ int pi = partition(arr,low,high); quickSort(arr, low, pi-1); quickSort(arr, pi+1, high); } } int partition (int arr[], int low, int high){ int pivot = arr[high]; int i = (low - 1); for (int j = low; j <= high- 1; j++){ if (arr[j] < pivot){ i++; swap(&arr[i], &arr[j]); } } swap(&arr[i + 1], &arr[high]); return (i + 1); } ``` ```java // 快速排序实现 (Java) public static void quickSort(int[] array, int start, int end) { if(start >= end) return; int pivotIndex = partition(array, start, end); quickSort(array, start, pivotIndex - 1); quickSort(array, pivotIndex + 1, end); } private static int partition(int[] array, int start, int end) { int pivotValue = array[end]; int index = start; for(int i=start;i<end;i++) { if(array[i]<pivotValue) { swap(array,i,index++); } } swap(array,end,index); return index; } ``` #### 二、深入理解编程语言特性 无论是使用C++还是Java参加竞,都需要深入了解所选语言的特点及其标准库的功能。例如,在C++中熟练运用STL容器类如vector、map等能够极大提高编码效率;而在Java里,则需熟知Collections框架下的各类集合类型及其实现原理。 #### 三、模拟实战训练 通过历年试题进行反复演练是非常有效的备考方式之一。虽然现在无法获取到最新的2024年具体题目,但是可以通过分析往年的考题来预测可能出现的新颖考点,并针对性加强薄弱环节。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值