当前位置: 首页 > news >正文

[蓝桥杯]三元组中心问题

三元组中心问题

题目描述

在数列 a1,a2,⋯,ana1​,a2​,⋯,an​ 中,如果对于下标 i,j,ki,j,k 满足 0<i<j<k<n+10<i<j<k<n+1 且 ai<aj<akai​<aj​<ak​,则称 ai,aj,akai​,aj​,ak​ 为一组递增三元组,ajaj​ 为递增三元组的中心。

给定一个数列,请问数列中有多少个元素可能是递增三元组的中心。

输入描述

输入的第一行包含一个整数 nn。

第二行包含 nn 个整数 a1,a2,⋯,ana1​,a2​,⋯,an​,相邻的整数间用空格分隔,表示给定的数列。

其中,2≤n≤1000,0≤数列中的数≤100002≤n≤1000,0≤数列中的数≤10000。

输出描述

输出一行包含一个整数,表示答案。

输入输出样例

示例

输入

5
1 2 5 3 5

输出

2

样例说明:

a2a2​ 和 a4a4​ 可能是三元组的中心。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

总通过次数: 3438  |  总提交次数: 3870  |  通过率: 88.8%

难度: 困难   标签: 2020, 模拟, 思维, 省模拟赛

三元组中心问题算法详解

问题描述

给定一个数列,统计有多少个元素可以作为递增三元组的中心,即存在下标 i, j, k 满足 0 < i < j < k < n+1 且 a_i < a_j < a_k

算法思路
核心思想

对于每个位置 j,检查其左侧是否存在小于 a[j] 的元素,右侧是否存在大于 a[j] 的元素。若两者同时满足,则 a[j] 可作为三元组的中心。

暴力法(推荐)
  1. ​时间复杂度​​:O(n²),适用于 n ≤ 1000(1000² = 1e6 次操作,在 1 秒内可完成)。
  2. ​空间复杂度​​:O(1),无需额外空间。
  3. ​步骤​​:
    • 遍历每个可能中心位置 j(下标 1 到 n-2)。
    • 向左扫描检查是否存在 a[i] < a[j]
    • 向右扫描检查是否存在 a[k] > a[j]
    • 若两者均满足,则计数器加 1。
预处理法(优化)
  1. ​时间复杂度​​:O(n),通过预处理避免嵌套循环。
  2. ​空间复杂度​​:O(n),需两个辅助数组。
  3. ​步骤​​:
    • 预处理 left_minleft_min[j] 表示 a[0..j-1] 的最小值。
    • 预处理 right_maxright_max[j] 表示 a[j+1..n-1] 的最大值。
    • 若 left_min[j] < a[j] < right_max[j],则 j 是中心。
代码实现(暴力法)
#include <iostream>
using namespace std;const int MAX_N = 1005;
int a[MAX_N];int main() {int n;cin >> n;for (int i = 0; i < n; i++) {cin >> a[i];}int count = 0;// 中心位置 j 的范围:下标 1 到 n-2for (int j = 1; j <= n-2; j++) {bool left_flag = false;// 向左扫描:找是否存在 a[i] < a[j]for (int i = 0; i < j; i++) {if (a[i] < a[j]) {left_flag = true;break; // 找到即退出}}if (!left_flag) continue; // 左侧无更小数则跳过bool right_flag = false;// 向右扫描:找是否存在 a[k] > a[j]for (int k = j+1; k < n; k++) {if (a[k] > a[j]) {right_flag = true;break; // 找到即退出}}if (left_flag && right_flag) {count++;}}cout << count << endl;return 0;
}
代码解析
  1. ​输入处理​​:读取数列长度 n 和数列 a
  2. ​中心位置遍历​​:
    • 下标 j 从 1 到 n-2(因首尾不能作为中心)。
  3. ​左侧检查​​:
    • 从 j-1 向左扫描至 0,若有 a[i] < a[j] 则标记 left_flag
  4. ​右侧检查​​:
    • 若左侧满足,再从 j+1 向右扫描至末尾,若有 a[k] > a[j] 则标记 right_flag
  5. ​计数条件​​:left_flag 和 right_flag 同时为真时计数。
实例验证
  • ​输入​​:n=5, a = {1, 2, 5, 3, 5}
  • ​验证过程​​:
    ja[j]左侧检查右侧检查是否计数
    121<2 → 满足5>2 → 满足
    251<5 → 满足3<5, 5=5 → 不
    331<3,2<3 → 满足5>3 → 满足
  • ​输出​​:2(与样例一致)
注意事项
  1. ​边界处理​​:
    • 当 n < 3 时直接输出 0(无法构成三元组)。
    • 中心位置 j 的范围严格限定为 [1, n-2](下标从 0 开始)。
  2. ​严格递增​​:
    • 必须满足 a[i] < a[j] < a[k],相等不成立。
  3. ​性能保障​​:
    • 最坏情况(如完全逆序数列)仍可在 1 秒内处理 n=1000。
优化建议

测试用例设计

测试用例预期输出验证点
n=2, [1,2]0最小长度边界
n=3, [3,2,1]0完全逆序数列
n=4, [1,1,1,1]0全相等
n=5, [5,4,3,2,1]0严格递减
n=5, [1,3,2,4,5]1中心在位置1(值3)
n=6, [1,2,3,4,5,6]4完全递增时的中心数量

  1. ​预处理法​​:

    #include <iostream>
    #include <algorithm>
    using namespace std;const int MAX_N = 1005;
    const int INF = 10001; // 大于数据最大值(10000)
    int a[MAX_N], left_min[MAX_N], right_max[MAX_N];int main() {int n;cin >> n;for (int i = 0; i < n; i++) cin >> a[i];// 初始化边界left_min[0] = INF; // 位置0无左侧元素right_max[n-1] = 0; // 位置n-1无右侧元素// 预处理左侧最小值for (int i = 1; i < n; i++) {left_min[i] = min(left_min[i-1], a[i-1]);}// 预处理右侧最大值for (int i = n-2; i >= 0; i--) {right_max[i] = max(right_max[i+1], a[i+1]);}int count = 0;for (int j = 1; j <= n-2; j++) {if (left_min[j] < a[j] && a[j] < right_max[j]) {count++;}}cout << count << endl;return 0;
    }

  2. 优势​​:时间复杂度降至 O(n),适合更大规模数据(如 n=10⁶)。

  3. ​二分优化​​(扩展):

    • 若数据规模扩大(如 n=10⁵),可对左右侧检查使用二分查找,将暴力扫描的 O(n) 降至 O(log n)
http://www.xdnf.cn/news/872929.html

相关文章:

  • Legal Query RAG(LQ-RAG):一种新的RAG框架用以减少RAG在法律领域的幻觉
  • Mysql避免索引失效
  • Qt 中实现文本截断(ellipsis)的功能。Qt 提供了此方法来处理过长的文本显示问题,例如在界面中限制文本长度并添加省略号(...)
  • Hugging Face 最新开源 SmolVLA 小模型入门教程(一)
  • 时序动作定位任务thumos14数据集标注文件处理
  • 【统计方法】蒙特卡洛
  • AT2401C中科微2.4g芯片PA
  • Starrocks中RoaringBitmap杂谈
  • 48V带极性反接保护-差共模浪涌防护方案
  • 5分钟了解JVM运行时数据区域
  • 【TCP/IP和OSI模型以及区别——理论汇总】
  • Vue2生命周期函数解析与应用
  • 项目练习:Vue2中el-button上的@click事件失效
  • 农业植保无人机核心技术从理论到实现
  • 无相关标签的精确零镜头密集检索
  • 60天python训练计划----day44
  • 理解网络协议
  • PX4 + D435i 进行gazebo仿真
  • Odoo 18 定期发送电子邮件报告(如KPI)配置指南
  • 力扣热题100之二叉树的直径
  • EMCC 13c 报错 “Metrics Global Cache Blocks Lost is at XXX“ 解决
  • TiDB单机生产环境下离线安装
  • 【Linux 】centos8搭建nextcloud全过程
  • 航芯MCU使用IAR+Jlink调试
  • C++算法训练营 Day8 字符串(1)
  • C++ 类一
  • 笔记 | docker构建失败
  • 乡村三维建模 | 江苏农田无人机建模案例
  • 深入解析FutureTask:原理与实战
  • 【RAG召回优化】rag召回阶段方法探讨