[sicily]1934. 移动小球

本文介绍了一种高效解决移动小球问题的方法,通过模拟双向链表的操作来实现小球位置的快速调整。该问题要求将一系列小球按照特定指令进行移动,并输出最终的小球排列顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1934. 移动小球

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

你有一些小球,从左到右依次编号为1,2,3,...,n. 你可以执行两种指令(1或者2)。其中, 1 X Y表示把小球X移动到小球Y的左边, 2 X Y表示把小球X移动到小球Y右边。 指令保证合法,即X不等于Y。 例如,初始状态1,2,3,4,5,6的小球执行1 1 4后,小球1被移动到小球4的左边,即2,3,1,4,5,6。如果再执行2 3 5,结点3将会移到5的右边,即2,1,4,5,3,6。 

Input

第一行为一个整数t(0<t<10),表示测试用例个数。每个测试用例的第一行为两个整数n(1<n<=500000)和m(0<m<100000),n表示小球的个数,m为指令条数,以下m行每行为一条指令。 

Output

为每个测试用例单独输出一行,从左到右输出最后序列,每个数字后面跟一个空格。 

Sample Input

2 
6 2 
1 1 4 
2 3 5 
5 1 
2 1 5 

Sample Output

2 1 4 5 3 6  
2 3 4 5 1  

关于线性表操作的问题。需要注意的是,根据题意很容易想到直接利用双向链表进行删除、插入,完成相关步奏,但是由于链表的存取特性,会超时。所以,采用节点数组的形式模拟双向链表。定义节点结构体,包含一个左右指针。

#include <iostream>
using namespace std;

struct node//定义节点,包含左右节点指针
{
    int left;
    int right;
}; 

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        cin>>n>>m;
        struct node a[n+1];//定义节点数组,a[i]表示编号为 i 的小球,a[i].left 为左边小球编号,a[i].right为右边小球编号
        for(int i=0; i<=n; i++)
        {
            a[i].left = i-1;
            a[i].right = i+1;
        }
        for(int i=0; i<m; i++)
        {
            int q,x,y;
            cin>>q>>x>>y;
            //首先删除  x 节点
            a[ a[x].right].left = a[x].left; // x右边节点的左指针指向x左边节点
            a[ a[x].left].right = a[x].right;//x 左边节点的右指针指向x右边节点 
            //然后在指定位置插入 x 节点
            if(q == 1)  // q ==1 ,执行 插入到 y节点的左边
            {
                a[x].left = a[y].left;
                a[x].right = y;       //修改x 节点的左右指针
                a[ a[x].left].right = x;
                a[y].left = x;         //指向x 节点
            }
            if(q == 2)   //q == 2, 执行插入到 y 节点的右边操作 
            {
                a[x].left = y;
                a[x].right = a[y].right;
                a[a[x].right].left = x;
                a[y].right = x;
            }
        }
        int index = 0;
        for(int i=0; i<n; i++)
        {
            index = a[index].right;
            cout<<index<<" ";
        } 
        cout<<endl;
    } 
    //system("pause");
    return 0;   
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值