算法学习_栈

以蓝书为学习参考,进行的栈的学习

例题1:

实现一个栈,支持Push,Pop和GetMin(查询栈中最小的值)在O(1)完成

算法实现思路:
建立两个栈,A存原本的数据,B存以栈底开头的每段数据的最小值

Push(X),在A中插入X,在B中插入min(B的栈顶数据,X)。执行GetMin只需要输出B.top()即可

例题2:

Input
8
I 2
I -1
I 1
Q 3
L
D
R
Q 2
Output
2
3
//对顶栈算法
#include <bits/stdc++.h>
using namespace std;
const int INF = -0x3F3F3F3F;
const int MAXN = 1000010;
// int s1[MAXN];
// int s2[MAXN];
int sum[MAXN];   //前x个数的和
int f[MAXN]; //前x个数中连续最大和
int main () {
    int cas;
    while(scanf("%d",&cas)!=EOF) {
        memset(sum, 0, sizeof(sum));
        memset(f, INF, sizeof f);
        int pos1 = 0;
        // int pos2 = 0;
        stack<int> s1;
        stack<int> s2;
        while(cas--) {
            string s;
            s.resize(5);
            scanf("%s", &s[0]);
            if(s[0] == ‘I‘) {
                // cin >> s1[++pos1];
                int temp;
                scanf("%d", &temp);
                // cout << 666 << " " << temp << endl;
                s1.push(temp);
                pos1++;
                sum[pos1] = sum[pos1 - 1] + temp;
                f[pos1] = max(f[pos1 - 1], sum[pos1]);
                // cout << pos1 << " III" << f[pos1] << endl;
            }
            else if(s[0] == ‘D‘) {
                // pos1--;
                if(s1.empty())
                    continue;
                pos1--;
                s1.pop();
            }
            else if(s[0] == ‘L‘) {
                if(s1.empty())
                    continue;
                // if(pos1 != 0) {
                //     s2[++pos2] = s1[pos1--];
                // }
                pos1--;
                int temp = s1.top();
                s1.pop();
                s2.push(temp);
            }
            else if(s[0] == ‘R‘) {
                if(!s2.empty()) {
                    // s1[++pos1] = s2[pos2--];
                    // sum[pos1] = sum[pos1 - 1] + s1[pos1];
                    // f[pos1] = max(f[pos1 - 1], sum[pos1]);
                    int temp = s2.top();
                    s2.pop();
                    s1.push(temp);
                    pos1++;
                    sum[pos1] = sum[pos1 - 1] + temp;
                    f[pos1] = max(f[pos1 - 1], sum[pos1]);
                }
            }
            else if(s[0] == ‘Q‘) {
                int x;
                scanf("%d", &x);
                printf("%d\n", f[x]);
            }
        }
    }
}

例题三:进出栈序列问题

利用Catalan数定义计算 C(2N, N) / (N + 1)   涉及数论计算知识。

#include<bits/stdc++.h>
using namespace std;
#define fir(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
const ll M=1e9;//M为压位的最大值
ll a[60004],l,sum[120004];
int n;
void Prime(int b,int f)
{
    for(int j=2;j*j<=b && b!=1;j++)//质因数分解.
        while(b%j==0)
        {
            sum[j]+=f;
            b/=j;
        }
    if(b)
        sum[b]+=f;
}
void High(ll c)
{
    for(int i=1;i<=l;i++)
        a[i]*=c;
    for(int i=1;i<=l;i++)
        a[i+1]+=a[i]/M,a[i]%=M;//我们需要压缩位置快速处理
    while(a[l+1])
        ++l;
}
int main()
{
    a[1]=1,l=1;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)//对于两个组合数相除,我们这道题目必须使用快速的质因数分解法,去处理.
        Prime(n+i,1);
    for(int i=2;i<=n+1;i++)
        Prime(i,-1);
    for(int i=2;i<=2*n;i++)
        for(ll j=0;j<sum[i];++j)
            High(i);//高精度
    printf("%lld",a[l]);
    for(ll i=l-1;i;--i)
        printf("%09lld",a[i]);//输出
    return 0;
}

例题四:

PS:改日研究研究我上面的算法==哪儿出错了(感觉出了玄学错误)

// // #include <bits/stdc++.h>
// #include <cstdio>
// #include <algorithm>
// using namespace std;
// typedef long long ll;
// const int MAXN = 100010;
// ll a[MAXN];
// int main () {
//     int n;
//     while((scanf("%d", &n) != EOF) && n) {
//         //memset(a, 0, sizeof a);
//         for(int i = 0; i < n; ++i) {
//             scanf("%lld", &a[i]);
//         }
//         ll p;
//         a[n + 1] = p = 0;
//         ll s[MAXN];ll w[MAXN];
//         s[0] = a[0];
//         w[0] = 1;

//         ll ans = 0;
//         for(int i = 1; i <= n + 1; ++i) {
//             if(a[i] > s[p]) {
//                 s[++p] = a[i];
//                 w[p] = 1;
//             }
//             else {
//                 ll width = 0;
//                 while(s[p] > a[i]) {
//                     width += w[p];
//                     ans = max(ans, (ll)width * s[p]);
//                     --p;
//                 }
//                 s[++p] = a[i];
//                 w[p] = width + 1;
//             }
//         }
//         printf("%ld\n", ans);
//     }
// }
#include <iostream>
#include <cstdio>
#include <stack>
using namespace std;

typedef long long ll;

const ll Maxn = 1e6 + 5;

stack <int> s;
int n, x;
ll a[Maxn], m, ans, Right[Maxn], Left[Maxn];

int main () {
    while (~scanf ("%d", &n), n) {
        ans = 0;
        a[0] = -1;
        a[n + 1] = -1;
        for (ll i = 1; i <= n; i++) {
            scanf ("%lld", &a[i]);
        }
        while (!s.empty()) {
            s.pop();
        }
        //从左向右
        s.push(0);
        for (ll i = 1; i <= n; i++) {
            for (x = s.top(); a[x] >= a[i]; x = s.top()) {
                s.pop();
            }
            Left[i] = x + 1;
            s.push(i);
        }

        while (!s.empty()) {
            s.pop();
        }
        //从右至左
        s.push(n + 1);
        for (int i = n; i > 0; i--) {
            for (x = s.top(); a[x] >= a[i]; x = s.top()) {
                s.pop();
            }
            Right[i] = x - 1;
            s.push(i);
            if ((Right[i] - Left[i] + 1) * a[i] > ans) {
                ans = (Right[i] - Left[i] + 1) * a[i];
            }
        }

        printf ("%lld\n", ans);

    }
    return 0;
}

原文地址:https://www.cnblogs.com/lightac/p/12571165.html

时间: 2024-11-03 22:07:52

算法学习_栈的相关文章

算法学习记录-栈的应用--表达式运算

前面做了栈的基本操作 总感觉需要做一个实际的例子来检验一下. 这里我将用栈来做一个简单的四则运算. 目标比较简单: 做一个带小括号(“()”)的四则运算,如果要加入到中括号(“[]”)或者大括号(“{}”),依次类推. 求一个表达式: 用下面这个算是做例子,程序最后应该可以算出任何带小括号的运算. 3+(32-6)*9+5*3-(3*(65-15)/5)+12; 方法一:后缀法. 1.了解中缀和后缀表示法 中缀表示法:刚才的那个算是就是中缀表示法,我们通常看到的数学符号就是中缀表示法,即数字在计

算法学习 - 最小栈的实现O(1)时间

// //  main.cpp //  MinStack2 // //  Created by Alps on 14/12/3. //  Copyright (c) 2014年 chen. All rights reserved. // #include <iostream> #include <vector> using namespace std; class MinStack { public: vector<int> stack; int min; void p

算法学习 - 括号匹配(栈实现)C++

括号匹配是栈最典型的应用了. 其实思路很简单,就是遇到一个左括号就压栈,遇到一个右括号就弹栈,看是否匹配就好了.最后检查下栈里是不是有剩余的括号就行了. 上代码~: // // main.cpp // bracketMatch // // Created by Alps on 14-7-28. // Copyright (c) 2014年 chen. All rights reserved. // #include <iostream> #define ElementType char usi

算法学习 - 后缀表达式 (C++ 栈实现)

后缀表达式就是把一个式子进行树的后序遍历.然后根据这个顺序来求值. 栈来实现的时候很简单. 例如中缀表达式:6 * [ 5 + ( 2 + 3 )  * 8 + 3 ] 则 后缀表达式为:6 5 2 3 + 8 * + 3 + * 下面上代码: // // main.cpp // postfixExpression // // Created by Alps on 14-7-28. // Copyright (c) 2014年 chen. All rights reserved. // #inc

算法学习 - 表达树的建立(后缀表达式法),树的先序遍历,中序遍历,后序遍历

表达树就是根据后缀表达式来建立一个二叉树. 这个二叉树的每个叶子节点就是数,真祖先都是操作符. 通过栈来建立的,所以这里也会有很多栈的操作. 树的先序遍历,中序遍历,后序遍历的概念我就不讲了,不会的自行百度,不然也看不懂我的代码. 下面是代码: // // main.cpp // expressionTree // // Created by Alps on 14-7-29. // Copyright (c) 2014年 chen. All rights reserved. // #includ

周总结(2017.2.16):第一周算法学习。

周总结:算法学习总结之DFS和BFS 一:DFS算法 目的:达到被搜索结构的叶节点. 定义:假定给定图G的初态是所有的定点都没有访问过,在G中任选一定点V为初始出发点,首先访问出发点并标记,然后依次从V出发搜索V的每个相邻点W,若W未曾出现过,则对W进行深度优先遍历(DFS),知道所有和V有路径相通的定点被访问. 如果从V0开始寻找一条长度为4的路径的话: 思路步骤: 先寻找V0的所有相邻点:dis{v1,v2,v3},V1没有访问过,所以对V1进行深度遍历并将V1标记为访问过,此时路径长度为1

算法学习(二) 全排列问题的非递归算法——模拟堆栈

前一段时间总结了全排列问题的几种递归解法,今天再总结一下如何通过对系统栈行为的模拟来非递归的实现全排列问题. 我们用一个数组stack[]来表示一个栈,用一个top指针来表示栈顶,用一个flags[]数组来标示每一个数字的可用性:用i来表示当前的状态. 初始状态top=0:i=-1:flags数组全为1: i递增,如果i没有越界并且flags[i]==1,那么就将i写入栈中,栈顶往前移动一位:最后把flags[i]赋值为0,i回溯到初始状态-1: 当栈顶越界,就将整个栈的信息打印出来,然后top

Python之路,Day21 - 常用算法学习

Python之路,Day21 - 常用算法学习 本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出.如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题.不同的算法可能用不同的时间.空间或效率来完成同样的任务.一个算法的优劣可以用空间复杂度与时间复杂度来衡量. 一个算

hdu 1269 迷宫城堡 (tarjan算法学习)

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7056    Accepted Submission(s): 3137 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A