Mergeable Stack ZOJ - 4016

Description

Given nn initially empty stacks, there are three types of operations:

1 sv: Push the value vv onto the top of the ss-th stack.

2 s: Pop the topmost value out of the ss-th stack, and print that value. If the ss-th stack is empty, pop nothing and print "EMPTY" (without quotes) instead.

3 st: Move every element in the tt-th stack onto the top of the ss-th stack in order.

Precisely speaking, denote the original size of the ss-th stack by S(s)S(s), and the original size of the tt-th stack by S(t)S(t). Denote the original elements in the ss-th stack from bottom to top by E(s,1),E(s,2),…,E(s,S(s))E(s,1),E(s,2),…,E(s,S(s)), and the original elements in the tt-th stack from bottom to top by E(t,1),E(t,2),…,E(t,S(t))E(t,1),E(t,2),…,E(t,S(t)).

After this operation, the tt-th stack is emptied, and the elements in the ss-th stack from bottom to top becomes E(s,1),E(s,2),…,E(s,S(s)),E(t,1),E(t,2),…,E(t,S(t))E(s,1),E(s,2),…,E(s,S(s)),E(t,1),E(t,2),…,E(t,S(t)). Of course, if S(t)=0S(t)=0, this operation actually does nothing.

There are qq operations in total. Please finish these operations in the input order and print the answer for every operation of the second type.

Input

There are multiple test cases. The first line of the input contains an integer TT, indicating the number of test cases. For each test case:

The first line contains two integers nn and qq (1≤n,q≤3×1051≤n,q≤3×105), indicating the number of stacks and the number of operations.

The first integer of the following qq lines will be opop (1≤op≤31≤op≤3), indicating the type of operation.

If op=1op=1, two integers ss and vv (1≤s≤n1≤s≤n, 1≤v≤1091≤v≤109) follow, indicating an operation of the first type.
If op=2op=2, one integer ss (1≤s≤n1≤s≤n) follows, indicating an operation of the second type.
If op=3op=3, two integers ss and tt (1≤s,t≤n1≤s,t≤n, s≠ts≠t) follow, indicating an operation of the third type.
It's guaranteed that neither the sum of nn nor the sum of qq over all test cases will exceed 106106.

Output

For each operation of the second type output one line, indicating the answer.

Sample Input

2
2 15
1 1 10
1 1 11
1 2 12
1 2 13
3 1 2
1 2 14
2 1
2 1
2 1
2 1
2 1
3 2 1
2 2
2 2
2 2
3 7
3 1 2
3 1 3
3 2 1
2 1
2 2
2 3
2 3
Sample Output

13
12
11
10
EMPTY
14
EMPTY
EMPTY
EMPTY
EMPTY
EMPTY
EMPTY
 


 题意:输入T,案例数,n, q。n代表栈的个数,q代表操作数。以下q行分别代表q个操作,

如果输入1,就要再输入s, v  即代表在第s个栈的栈顶入v。如果输入2,就再输入s,代表弹出(即输出)第s个栈的栈顶元素。如果输入3,再输入s, t 代表要把第t个栈的元素移到第s个栈的栈顶,(移入顺序为元素移出第t个栈的反序)。


#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<stack>
using namespace std;
int n, q;
const int maxn=300010;
int top[maxn], nextt[maxn], mapp[maxn], bottom[maxn];
//mapp数组记录所有的数;
//top数组记录每个栈的栈顶元素在a中的下标;bottom数组记录每个栈的栈底元素在mapp中的下标;
//next数组记录每个栈的栈顶的下一个元素在mapp中的下标;
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &q);
        int sum = 0;//mapp数组的下标;
        memset(top, 0, sizeof(top));
        memset(nextt, 0, sizeof(nextt));
        memset(bottom, 0, sizeof(bottom));
        while(q--)
        {
            int op;
            scanf("%d", &op);
            //操作1,输入s,v,第s个栈的栈顶压入元素v;
            if(op==1)
            {
                int s, v;
                scanf("%d%d", &s, &v);
                mapp[++sum] = v;//v元素放入数组mapp中;

                //如果s这个栈的栈底为空,栈底就等于v这个元素在mapp中的下标;
                if(bottom[s]==0)
                    bottom[s] = sum;

                nextt[sum] = top[s];//刚进栈的这个元素的下一个元素是原来栈的栈顶,也就是在他之前进栈的那个元素;
                top[s] = sum;//第s栈的栈顶为v这个元素在mapp中的下标;
            }
            //操作2,输入s,弹出第s个栈的栈顶元素;
            if(op==2)
            {
                int s;
                scanf("%d", &s);

                //如果s栈不为空;
                if(top[s])
                {
                    printf("%d\n",mapp[top[s]]);//输出mapp中s栈栈顶位置的元素;
                    top[s] = nextt[top[s]];//s栈的栈顶元素就变为原来栈的栈顶元素的下一个,也就是还没有弹出栈时的栈顶元素的下一个; 指向下一个,相当于弹出栈顶;
                    
                    //如果s栈在弹出后空了,s栈的栈底也变为空;
                    if(top[s]==0)
                        bottom[s] = 0;
                }
                //如果s栈空了,直接输出“EMPTY”;
                else
                    printf("EMPTY\n");
            }
            //操作3,t栈移到s栈顶;
            if(op==3)
            {
                int s, t;
                scanf("%d%d", &s, &t);
                if(top[t]!=0)
                {
                    //如果s栈为空,s栈的底就是t的底;
                    if(bottom[s]==0)
                        bottom[s] = bottom[t];

                    nextt[bottom[t]] = top[s];//t这个栈的栈底元素的下一个元素是s栈的栈顶元素;即t的底部指向s的顶;
                    top[s] = top[t];//s栈的顶变成t的顶;
                    bottom[t] = top[t] = 0;//t栈移动后,清空;
                }
            }
        }
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值