蓝桥杯备考冲刺必刷题(C++) | 3416 四元组问题

学习C++从娃娃抓起!记录下蓝桥杯备考比赛学习过程中的题目,记录每一个瞬间。

附上汇总贴:蓝桥杯备考冲刺必刷题(C++) | 汇总-CSDN博客


【题目描述】
从小学开始,小明就是一个非常喜欢数学的孩子。他喜欢用数学的方式解决各种问题。在他的高中时期,他遇到了一个非常有趣的问题,那就是给定一个长度为$$n$$的整数数组$$nums ,判断是否存在四个不同的下标 , 判断是否存在四个不同的下标 ,判断是否存在四个不同的下标a,b,c,d 使得 a < b < c < d a\lt b\lt c\lt d a<b<c<d, 并且 n u m s [ d ] < n u m s [ c ] < n u m s [ a ] < n u m s [ b ] nums[d]<nums[c]<nums[a]<nums[b] nums[d]<nums[c]<nums[a]<nums[b]
小明非常喜欢这个问题,他决定用数学的方式来解决它。他首先想到了一个非常简单的方法,那就是暴力枚举。他用四个循环来枚举所有可能的下标组合,然后判断是否满足条件。但是这个方法非常耗时,当 n n n很大时,计算量会非常大。
所以请求你给出一个快速智慧的解决办法。
【输入】
输入仅两行,第一行包含一个整数 n n n,第二行包含 n n n个整数,其含义如上所述。
【输出】
输出仅一行,包含一个字符串,YES表示题目存在上面所描述的情况, 否则输出NO。
【输入样例】

4
3 4 2 1

【输出样例】

YES

【代码详解】
[图片]

#include <bits/stdc++.h>
using namespace std;
int n, nums[500005], min_r[500005];
bool FoursNumberFind() {
    stack<int > st;  // 构造单调递减栈
    int k=-1e9, INF=1e9;
    for (int i=0; i<n; i++) {  // 初始化min_r数组,记录最小值
        min_r[i] = 1e9;
    }
    for (int i=n-2; i>=0; i--) {  // 记录第i个数右边的最小值
        min_r[i] = min(min_r[i+1], nums[i+1]);
    }
    for (int i=0; i<n; i++) {
        
        if (nums[i]<k) {  // 如果存在nums[i]<nums[a],即存在nums[c]<nums[a]<nums[b]的情况
            if (nums[i]>min_r[i]) return true;  // 如果c的右边有比nums[c]小的数,有则表示存在下标d,返回true
        }
        // cout << "11 " << endl;
        while (!st.empty() && st.top()<nums[i]) {  // 如果栈不为空,且栈顶小于nums[i]
            // cout << "st.top num[i] " << st.top() << " " << nums[i] << endl;
            // 需要找到满足小于nums[b]的最大k值,即nums[a]
            k = max(k, st.top());
            // cout << "k " << k << endl;
            st.pop();
        }
        st.push(nums[i]);  // 压入栈顶,即更新nums[b]
    }
    return false;
}
int main()
{
    cin >> n;
    for (int i=0; i<n; i++) {
        cin >> nums[i];
    }
    if (FoursNumberFind()) {
        cout << "YES" << endl;
    } else {
        cout << "NO" << endl;
    }
    return 0;
}

【运行结果】

4
3 4 2 1
YES
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值