【链表】洛谷_1160 队列安排

题意

给出n个人,一开始1号站在第一位,之后给出n-1个操作,每次给出一对数a b,如果b为0那么就把人i插到人a的左边,否则插到人a的右边。后面给出m个操作,每次给出一个数,代表把这个人从队列里删掉(如果已经不在队列里就忽视),最后输出这个队列。

思路

这道题我们可以用到双向链表,然后按照题目说的做就可以了。

代码

#include<cstdio>
using namespace std;
struct node{
    int l,r,v;//l,r分别代表这个人左右站的人,v代表这个人的编号(好像可以不用这样)
}s[100001];
int n,a,b,mal;//mal记录最左边的点,输出时从这开始遍历
void insl(int old,int now) {
    s[s[old].l].r=now;//把now插到old的左边,那么old的左边的点的右边就会指向now
    s[now].r=old;//now这个点在左边,所以右边就是old
    s[now].l=s[old].l;//now的左边就是old之前的左边
    s[old].l=now;//now插在old左边
    if (mal==old) mal=now;//更新最左边的点
}
void insr(int old,int now) {
    s[s[old].r].l=now;//把now插在右边,那old之前的右边的左边就会变成now
    s[now].r=s[old].r;//now的右边指向old之前的右边
    s[now].l=old;//now插在old的右边,所以now的左边是old
    s[old].r=now;//old的右边就是now
}
void del(int x) {
    s[s[x].l].r=s[x].r;//x删除了,所以x左边和右边的点会连起来
    s[s[x].r].l=s[x].l;
    if (x==mal) mal=s[x].r;
    s[x].l=s[x].r=0;s[x].v=-1;
}
int main() {
    scanf("%d",&n);
    s[1].v=1;
    mal=1;
    for (int i=2;i<=n;i++) {
        scanf("%d%d",&a,&b);
        s[i].v=i;
        if (!b) insl(a,i);//插入左边
        else insr(a,i);//插入右边
    }
    scanf("%d",&n);
    for (int i=1;i<=n;i++) {
        scanf("%d",&a);
        if (s[a].v<0) continue;//已经不在了就可以忽视
        del(a);//删除
    }
    for (;s[mal].v;mal=s[mal].r)//遍历链表输出
        printf("%d ",s[mal].v);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值