高山算法?其实是贪心啦!

近来往往看到过一种类型的贪心的题,就是那种不明所以却有感觉好神奇啊的那种题。
直接上例题。

AtCoder 064 D

那么就来想一想这道题的做法,一开始以为是道栈的题,但发现栈底无法处理,那么就双向队列吧,但发现中间无法插入,那么就splay的合并分裂吧,那么最小字典序呢?拜托,这是beginner的难度。。。
思考了一会儿,
对于一串括号,我只需要正着搜索,反着搜索不就行了吗?
每次记录右减左与左减右的max再printf就可以了吧。。。
naive code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;
string st;
stack<int> sa;
int a[1000],sum[1000],len=1,cnt=0,rd=0,ld=0,l=0,r=0;
int n,flag=-1;
int main(){
    cin>>n>>st;
    for(register int i=0;i<n;i++){
        if(st[i]=='(')a[i]=1;
        else a[i]=0;
    }
    for(register int i=0;i<n;++i){
        if(a[i]==1)l++;
        else r++;
        rd=max(rd,r-l);
    }
    l=r=0;
    for(register int i=n-1;i>=0;--i){
        if(a[i]==1)l++;
        else r++;
        ld=max(ld,l-r);
    }
    for(register int i=1;i<=rd;++i)cout<<'(';
    for(register int i=0;i<n;++i)cout<<st[i];
    for(register int i=1;i<=ld;++i)cout<<')';
    return 0;
}

由此引入我所谓的高山算法。
为什么叫做高山算法?因为每走一步都要测量一下,当前维护信息的值,而最后所需的值并不一定是末尾所处理的值,而是过程中某一处的特值,一般是最大最小值。
Q:为什么叫做高山算法?
A:这是模拟爬山的测量的一个过程,更类似于扫描线,而已经有爬山这个算法了,所以就叫高山算法吧。
Q;这个算法有什么用?
A:其实并没有什么意思,只是提出这样一个类扫描线的贪心算法,有助于理解 O(n) 复杂度类寻找简单类型的查询问题。
Q:还有什么例题?(该不会是你一时兴起决定的吧?)
A:下方(是的)。

例一 Maximum Sum Sequence

好吧,确实是道naive的题,秒了。代码Leaderboard中有。

例二 Maximum Sum Sequence II

这道题就有意思了吧,还是高山算法,如何做?
其实加个预处理就好了。。。
代码还是见Leaderboard。

LAST ONE 例三

Largest Rectangle in Histogram

之所以不发链接,是因为这道题蛮经典的,到处到可测,例如SPOJ。
这是体现出高山算法在贪心算法中都有无与伦比的“脑洞值”的优秀题目,所以这道题值得一做。

问题描述:给定一个长度为n的直方图,我们可以在直方图高低不同的长方形之间画一个更大的长方形,求该长方形的最大面积。例如,给定下述直方图,

这里写图片描述

我们可以以高度5宽度2画一个更大的长方形,如下图,该长方形即是面积最大的长方形。该问题是难度比较大的问题,但是很出名,经常作为面试题出现。用高山算法可以做到O(n)的复杂度,非常巧妙,并从二维三维角度对问题进行了扩展。

这里写图片描述
仔细思考吧,毕竟高山算法其实挺简单的。

高山==单调队列/单调栈?

不是这样,单调队列需要维护一整个队列的单调性,单调栈同理,而高山算法不改变遍历时的处理顺序,不用额外的数据结构存储,是一个面向答案编写程序的算法。

总结

没什么好说的,这样一个奇妙的算法究竟能够延展到什么程度?静待吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值