stack(hdu)

题意:有n个栈,第i个栈刚开始只放了i,有m个操作,每次把ai放到bi里,求最后每个栈里元素的个数和元素

模拟肯会超时,那么我们就想用双链表来写

s数组用来存一个数的前面相连的数或者后面的数(因为堆的话一个数只能连两个数)

struct name{
	int pre,next;
}s[N];

sta数组用来记录栈顶和栈底元素

struct po{
	int top,bot;
}sta[N];

f数组来记录这个数输出过没有,num来记录每个栈的元素的个数

int f[N],num[N];

刚开始初始化的时候每个栈的栈顶和栈底都是i本身,然后num都是1,f初始化为0,每个数没有与他相连的数,所以前面后面都是0

for(int i=1;i<=n;i++){
			num[i]=1;
			sta[i].top =sta[i].bot =i;
			f[i]=0;
			s[i].next =s[i].pre =0;
		}

然后我们对于把a这个栈放到b这个栈的add操作:

我们分别用xyzq来记录a的栈顶和栈底,b的栈顶和栈底

把a放入b,那么a的栈底就是b的栈顶

a的num要加到b的num里去,a的num变成0

然后a的栈顶x就会连上b的栈顶z,判断一下x有没有与他相连的数

如果没有就把z连到x的后面next,如果有就连到x的前面pre

z的情况也是一样,如果z后面没有的话就连到后面,有的话就连到前面

#include<iostream>
#include<algorithm>
#include<cmath>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<cstring>
#include<list>
#include<map>
#include<cstdio>
typedef long long ll;
typedef int64_t s64;
using namespace std;
struct node{
    int pre,next;
}s[200005];
struct stac{
    int top,bot;
}sta[200005];
int num[200005];
void add(int a,int b){
    int x=sta[a].top;
    int y=sta[a].bot;
    int z=sta[b].top;
    int q=sta[b].bot;
    if(!num[b]){        //b栈中没有东西
        sta[b].bot=x;   //a的头变b的底
        sta[b].top=y;   //a的底比b的头
        sta[a].top=sta[a].bot=0; //把a头和底置0 
    }
    else{              //b栈有东西
        if(!s[x].next){   //判断a栈中的头是否是next空(因为此题为双向链表不能确定是next还是pre)
            s[x].next=z;
        }   
        else{   //判断a栈中的头是否是pre空
            s[x].pre=z;
        }
        if(!s[z].next){   //判断b栈中的头是否是next空(双向链表所以a和b是需要相互连接的)
            s[z].next=x;
        }
        else{   //判断b栈中的头是否是pre空
            s[z].pre=x;
        }   //在这之前都是在做将ab栈连接起来的操作
        sta[b].top=y;   //把a的底变b的头
        sta[a].top=sta[a].bot=0;   //把a的头和底置0
    }
    num[b]+=num[a];
    num[a]=0;
}
int sig[200005];
int main(){
    int n,m;
    while(cin>>n>>m){
        for(int i=1;i<=n;i++){   //初始化n个栈
            s[i].pre=s[i].next=0;
            sta[i].top=sta[i].bot=i;
            num[i]=1;
            sig[i]=0;
        }
        int x,y;
        while(m--){
            cin>>x>>y;
            if(num[x]==0)
                continue;
            add(x,y);
        }
        for(int i=1;i<=n;i++){
            int k=sta[i].top;
            cout<<num[i];   //输出当前栈中的数据个数
            if(num[i]){     //判断是否栈中有数据   
                while(k){
                    cout<<" "<<k;   
                    sig[k]=1;   //每次找到并且输出后都需要标记
                    if(s[k].next&&sig[s[k].next]!=1){   //寻找下一个数据,因不确定是next还是pre所以需要进行以下的判断
                        k=s[k].next;
                    }
                    else if(s[k].pre&&sig[s[k].pre]!=1){
                        k=s[k].pre;
                    }
                    else{
                        k=0;   //找不到下一个退出循环
                    }
                }
            }
            cout<<endl;
        }
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值