Mergeable Stack (链表)(2019省赛训练-5)

版权声明:转载时 别忘了注明出处 https://blog.csdn.net/ZCY19990813/article/details/89105880
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

题意:n个栈, q次操作,  操作1,后面两个数a,b, 代表往a栈中放入b,  操作2,后面一个数a,代表在a栈中取走栈顶元素,

操作3,后面两个数a,b,代表把b栈的元素压入b栈中。

注意:1.栈先进后出。   2.数据量3e5,不能开那么多栈(会内存超限),要用链表来模拟栈的过程。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <map>
#include <set>
#define MAX 0x3f3f3f3f
//#define fori(a,b) for(LL i=a;i<=b;i++)
//#define forj(a,b) for(LL j=a;j<=b;j++)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double PI = acos(-1);
const ll M=3e5+7;
const ll mod=1e9+7;
struct A  //单个链表
{
    ll num;  //结点的值
    A *l;  //用来指向前一个元素
    A *r;  //用来指向后一个元素
};
struct B   //多个链表
{  
    A *head;  //每一个链表的头指针
    A *endd;  //每一个链表的尾指针
}b[M];
int main()
{
    // freopen("//home//acm//桌面//in","r",stdin);
    ll t,n,q,i,j,e,x,y;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&n);
        scanf("%lld",&q);
        for(i=1;i<=n;i++)    //首先要把每个结点赋值为空
            b[i].head=NULL,b[i].endd=NULL;
        for(i=0;i<q;i++)
        {
            scanf("%lld",&e);
            if(e==1)
            {
                scanf("%lld%lld",&x,&y);
                A *t=new A;   //创建一个A类型的链表
                t->num=y;
                t->r=NULL;
                if(b[x].head==NULL&&b[x].endd==NULL)  //如果现在链表里面没有东西
                {
                    t->l=NULL;
                    b[x].head=t;
                    b[x].endd=t;
                }
                else
                {
                    t->l=b[x].endd;
                    b[x].endd->r=t;
                    b[x].endd=t;
                }
            }
            else
            if(e==2)
            {
                scanf("%lld",&x);
                if(b[x].head==NULL)    //如果现在链表里面没有东西
                    printf("EMPTY\n");
                else            //如果现在链表里面有东西,因为当时存的时候,是往链表的后面
                {               //插入,所以链表尾就相当与栈顶
                    A *t=b[x].endd;
                    printf("%lld\n",t->num);
                    b[x].endd=t->l;
                    if(t->l==NULL)
                        b[x].head=NULL;
                    delete t;   //释放删除结点的空间
                }
            }
            else
            if(e==3)
            {
                scanf("%lld%lld",&x,&y);//y里面的放到x里面
                if(b[y].head==NULL)   //如果y链表为空,不用操作
                    continue;
                if(b[x].head==NULL)   //如果x链表为空,记得把y赋值NULL
                {
                    b[x].head=b[y].head;
                    b[x].endd=b[y].endd;
                    b[y].head=NULL;
                    b[y].endd=NULL;
                }
                else               //如果两个链表里面都有东西,直接将y的头连到x的尾部
                {                  //在相应更改x的尾指针,y的头指针和尾指针
                    A *t=b[y].head;
                    t->l=b[x].endd;
                    b[x].endd->r=b[y].head;
                    b[x].endd=b[y].endd;
                    b[y].head=NULL;
                    b[y].endd=NULL;
                }
            }
        }
    

其实用链表模拟栈的操作时间复杂度更低了,重点在操作3上面,直接一步操作就行,如果用栈时间复杂度就更高了。

scanf() 比 cin 复杂度会更低。

猜你喜欢

转载自blog.csdn.net/ZCY19990813/article/details/89105880
今日推荐