芜湖一中 新C1班作业 (1)

B3630 排队顺序

(1)

有 n 个人,每个人只知道自己的身后是谁,已知第一位人的编号,输出整个排列顺序。

我们可以使用链表完成:

  • 建立数组 nxtnxt 表示每个人身后人的编号;
  • 定义 nownow 表示当前指针,初始为 headhead;
  • 如果 nownow 不是 00 时,输出 nownow,并将 nownow 变为下一个指针位置。

比如数据:4 6 0 2 3 5。

我们可以先列一个表格。

i123456
nxti​460235

假设队首为 1 号,则 �i 次循环 nownow 和 nxtnownxtnow​ 的值如下:

inownownxtnownxtnow​
111nxt1=4nxt1​=4
244nxt4=2nxt4​=2
322nxt2=6nxt2​=6
466nxt6=5nxt6​=5
555nxt5=3nxt5​=3
633nxt3=0nxt3​=0

所以输出为:1 4 2 6 5 31 4 2 6 5 3。

但是,如果不知道 headhead 怎么办呢?

很简单,如果一个编号如果没有出现在任何一个人的后面,那么他就是第一个人。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int a[N], n, first;
int main(){
    cin>> n;
    for(int i = 1; i <= n; i++)
        cin>> a[i]; 
    cin>> first;
    int now = first; 
    cout<< first<< " ";
    while(a[now] != 0)
    {
        cout<< a[now]<< " ";
        now = a[now];
    } 
    return 0;
}
 

B3631 单向链表

(2)

维护一张初始只有元素 11 的表,支持以下操作:

  • 1 x y:将元素 y 插入到 x 后;
  • 2 x:询问 x 后面的元素是什么;
  • 3 x:从表中删除 x 后的元素。

如果有操作二,输出一个数字,并换行。

我们依旧可以看成一些人在排队,只不过多了一个插队和走人的操作。

我们假设初始排队顺序为:1 4 2 31 4 2 3。

若 5 号同学插队到 4 号的后面,那么会发生什么?

我们先来看看初始的链表情况:

i1234
nxti​4302

此时,5 号同学插入 4 号的后面,那么链表就会变为:

i12345
nxti​4?0??

此时 2 4 号的位置发送变化,我们一个一个的分析:

  • 2 号的后面没有影响,所以 2 号的后面依旧是 3 号;
  • 5 号插到了 4 号的后面,所以 5 号的后面将会是原本 4 号后面的人,所以 5 号的后面为 2 号;
  • 4 号的后面插进了一个 5 号,所以 4 号的后面变为 5 号。

所以整个链表变为:

i12345
nxti​43052

所以用代码实现是这样:

这时,2 号同学离开了队伍,那么又会发送什么?

那么链表会变为:

i12345
nxti​4before 3before 305?
  • 5 号的后面原本是 2 号,但是 2 号离开了,2 号原本的后面是 3 号,所以 5 号的后面变为了 3 号。

所以变为:

i1345
nxti​4053

改进:

我们可以用结构体减少内存。

原链表为:

i12345678910
ai​9704

浪费了很多的空间。

我们可以使用结构体:

i12345
node.valnodei​.val11447799
node.nxtnodei​.nxt44330022

#include <bits/stdc++.h>
using namespace std;
const int N = 1000005;
int a[N], b[N];
int q, n, x, y;
void cz1(int x, int y)
{
    a[y] = y;
    b[y] = b[x];
    b[x] = y;
}
void cz3(int x)
{
    b[x] = b[b[x]];
}    
int main()
{
    cin >> q;
    a[1] = 1, b[1] = -1;
    while (q--)
    {
        cin >> n;
        if (n == 1) cin >> x >> y, cz1(x, y);
        else if (n == 2)
        {
            cin >> x;
            if (b[x] == -1) cout<< 0 << endl;
            else cout << a[b[x]] << endl;
        }
        else cin >> x, cz3(x);
    }
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值