当前位置: 首页 > 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.lqws.cn/news/116659.html

相关文章:

  • 将音频数据累积到缓冲区,达到阈值时触发处理
  • Python爬虫(48)基于Scrapy-Redis与深度强化学习的智能分布式爬虫架构设计与实践
  • 四、Sqoop 导入表数据子集
  • 什么是内网映射?如何将内网ip映射到外网访问?
  • 数据结构 [一] 基本概念
  • 力扣热题100之二叉树的直径
  • 【设计模式-4.9】行为型——命令模式
  • 学习STC51单片机27(芯片为STC89C52RCRC)
  • 3D视觉重构工业智造:解码迁移科技如何用“硬核之眼“重塑生产节拍
  • 海康网络摄像头实时取帧转Opencv数组格式(h,w,3),已实现python、C#
  • OPENCV重点结构体Mat的讲解
  • Cocos creator游戏开发面试题
  • CentOS7 + JDK8 虚拟机安装与 Hadoop + Spark 集群搭建实践
  • Kafka入门-集群基础环境搭建(JDK/Hadoop 部署 + 虚拟机配置 + SSH 免密+Kafka安装启动)
  • 解决IDE编译JAVA项目时出现的OOM异常问题
  • 分类与逻辑回归 - 一个完整的guide
  • springboot ErrorController getErrorPath() 版本变迁
  • Springfox 和 Knife4j 集成404 问题
  • 期末复习(学习)之机器学习入门基础
  • 705SJBH超市库存管理系统文献综述
  • Oracle OCP与MySQL OCP认证如何选?
  • SpringBoot(七) --- Redis基础
  • Ubuntu 25.10 将默认使用 sudo-rs
  • web全栈开发学习-01html基础
  • PyTorch学习笔记 - 损失函数
  • C++ 使用 ffmpeg 解码本地视频并获取每帧的YUV数据
  • 大数据学习(128)-数据分析实例
  • 数据结构(8)树-二叉树
  • [ Qt ] | 与系统相关的操作(二):键盘、定时器、窗口移动和大小
  • Go语言爬虫系列教程4:使用正则表达式解析HTML内容