Mergeable Stack ZOJ - 4016

Mergeable Stack

ZOJ - 4016

题目链接



这道题真的很坑爹,一开始做的时候感觉很简单的一道关于栈操作的题,然后就用了stl里的stack结果爆内存了,然后改了三次还是不行,后来还用了string字符串,先是超时后来又爆内存,大概是因为stl里面的容器内存不够时是二倍扩展,每次二倍就指数增长了,然后题目再恰好弄个数据让你一扩展乘2就超过题目要求内存了,真的坑。
后来听说有同学自己写的链式栈过了,因为是用一个申请一个内存,然后写了个答案错误妈的不改了。再后来看了大佬的代码,感觉很巧妙。

思路是把所有数字都存在一个数组a中,然后用三个数组top,Next,bottom分别记录栈顶栈底和栈顶下一个数字在a数组的下标数字,这样最多只用四个3e5的数组不会超内存也不回超时
code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,q;
const int maxn = 300005;
int top[maxn],Next[maxn],a[maxn],bottom[maxn];
//a数组记录所有的数,top记录每个栈的栈顶元素在a中的下标,
//Next记录每个栈栈顶的下一个元素在a中的下标,bottom记录栈底元素在a中的下标
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&q);
        int cnt = 0;//a数组的下标
        memset(top,0,sizeof(top));
        memset(Next,0,sizeof(Next));
        memset(bottom,0,sizeof(bottom));//初始化
        while(q--){
            int op;
            scanf("%d",&op);
            if(op == 1){
                int s,v;
                scanf("%d%d",&s,&v);
                a[++cnt] = v;//元素放入数组a
                if(bottom[s] == 0)//如果这个栈栈底为空,栈底等于这个元素在a中的下标
                    bottom[s] = cnt;
                Next[cnt] = top[s];//这个下标cnt下一个元素指向原本的栈顶元素在a中下标
                top[s] = cnt;//更新栈顶
            }
            if(op == 2){
                int s;
                scanf("%d",&s);
                if(top[s]){//如果栈不空
                    printf("%d\n",a[top[s]]);//输出a中这个位置的元素
                    top[s] = Next[top[s]];//指向下一个,相当于弹出栈顶
                    if(top[s] == 0) bottom[s] = 0;//如果空了,bottom也变为空
                }
                else//如果栈空输出empty
                    printf("EMPTY\n");
            }
            if(op == 3){
                int s,t;
                scanf("%d%d",&s,&t);
                if(top[t] != 0){
                    if(bottom[s] == 0) bottom[s] = bottom[t];//如果s是空的,s的底就是t的底
                    Next[bottom[t]] = top[s];//t的底部指向s的顶
                    top[s] = top[t];//s的顶变成了t的顶
                }
                bottom[t] = top[t] = 0;//t移动后清空
            }
        }
    }
    return 0;
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值