单调栈萌新讲解

单调栈

哈。。。怎么开始介绍这个单调栈是一个小问题。。。所以就直接讲他的功能了:在入栈时遵循单调原则,可以求出一个元素向左和向右所能扩展的最大长度(>=或者<=这个元素)

具体操作:

例1:求一个元素的右侧的最近比他大的元素位置(BZOJ3401);

INPUT:

输入一个n代表元素个数,输入n个元素;

6

3 2 6 1 1 2

OUTPUT:
输出位置,没有则输出0;

3 3 0 6 6 0

思路:

首先能不能随便一点,我就是维护一个栈的单调递增(不管三七二十一),那么我要如何利用呢?

①   3进栈;

②   2比栈顶元素小,不要;

③   6比栈顶元素大,进去;

④   。。。。。等等窝们不是要求一个元素比他的最近么?这样子2都不要了。。然后6过来了还进栈。。这不是背道而驰了。

所以方案错误;

那么不是维护单调递增,就是维护一下单调递减呗;

①   3进栈

②    2比3小进栈

③   6比2大,咦?一下就是6比2大,而且后面都没有碰到,所以6一定是2的单侧最近,然后2出栈,并且2的答案就是6元素的位置。然后看3,3还是比6小,OK,满足。最后把6进栈。

④   1进栈

⑤   1进栈

⑥   2的时候,栈里面的两个1出栈,然后2进栈

⑦    最后注意,栈里面还有6和2这两个元素,可惜没有他们的答案,那就是0;

#include<bits/stdc++.h>
using namespace std;

struct node{
    int id;
    int x;
}a[2000100];
int ans[2000100];

int main()
{
    int n; scanf("%d",&n);
    for(int i = 1;i <= n;i ++){
        scanf("%d",&a[i].x);
        a[i].id = i;
    }
    stack<node>s;
    for(int i = 1;i <= n;i ++){
        while(!s.empty() && a[i].x > s.top().x){
            ans[s.top().id] = a[i].id;
            s.pop();
        }
        s.push(a[i]);
    }
    while(!s.empty()){
        ans[s.top().id] = 0;
        s.pop();
    }
    for(int i = 1;i <= n;i ++)
        if(i == 1) printf("%d",ans[i]);
        else printf(" %d",ans[i]);
    printf("\n");
    return 0;
}

引用黄学长的做法:倒序维护单调递减栈,其实也一样,倒序的时候,碰到元素如果比他大就要把栈里元素pop掉,如果比栈顶小的话那就是说栈顶元素位置就是答案;

所以窝们先可以得出一个小感悟:

即:单调栈就是通过维护栈内元素单调递增或者单调递减,判断栈顶元素和当前元素的关系处理,然后得到窝们想要的答案(其实就是一个元素向左和向右所能扩展的最大长度);

这里还有一题(poj2796):实际上就是对于一个元素,求两端的最长延伸;

题意:给你N个数,求在某段区间的最小值*这段区间所有元素之和,求最大;

(PS:还是如此窝们只能说我维护一个单调递增看看,行不行?不行递减看看?(或许题目做多了就熟能生巧了吧);我觉得一个栈存一个结点的所需要的所以信息比较好理解,所以上面的代码也是这样。)

这题的思路:

首先区间和,利用前缀和,然后减一减就可以搞出来;

那么就是确定每个元素,当这个元素是最小的时候,我要知道他之前和之和有多少个比他大的,即比他小的最近的两个端点。

通过上面的写法,可以搞两发单调栈搞出那个区间长度;

不过还是很欣赏紫忆的这篇(<=可点 >。<);

维护一个单调递增栈,并且细节上处理一个元素的两个位置,依次从左往右,在当点元素与栈顶元素比较时;

①   a[i]>q.top()那么就是入栈;

②   a[i]<q.top()时,那么也就是说对于这个元素啊,q.top()的元素的右边最小就是a[i]位置,那么a[i]的前延伸要变成出栈顶元素的前延伸,出栈,那么此时栈不为空的话,栈顶元素的向后延伸位置要变成之前出栈元素的后驱。

③   期间判断一个最大值;

虽然麻烦一点吧,但是还是很妙啊~

也可以两次,一次操作细节上很多吧;

 嘿嘿嘿~~

 

版权声明:本文为博主原创文章,未经博主允许可以转载。 https://blog.csdn.net/KEYboarderQQ/article/details/52723059

转载自: https://blog.csdn.net/KEYboarderQQ/article/details/52723059

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值