B3630 排队顺序
(1)
有 n 个人,每个人只知道自己的身后是谁,已知第一位人的编号,输出整个排列顺序。
我们可以使用链表完成:
- 建立数组 nxtnxt 表示每个人身后人的编号;
- 定义 nownow 表示当前指针,初始为 headhead;
- 如果 nownow 不是 00 时,输出 nownow,并将 nownow 变为下一个指针位置。
比如数据:4 6 0 2 3 5。
我们可以先列一个表格。
i | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
nxti | 4 | 6 | 0 | 2 | 3 | 5 |
假设队首为 1 号,则 �i 次循环 nownow 和 nxtnownxtnow 的值如下:
i | nownow | nxtnownxtnow |
---|---|---|
1 | 11 | nxt1=4nxt1=4 |
2 | 44 | nxt4=2nxt4=2 |
3 | 22 | nxt2=6nxt2=6 |
4 | 66 | nxt6=5nxt6=5 |
5 | 55 | nxt5=3nxt5=3 |
6 | 33 | nxt3=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 号的后面,那么会发生什么?
我们先来看看初始的链表情况:
i | 1 | 2 | 3 | 4 |
---|---|---|---|---|
nxti | 4 | 3 | 0 | 2 |
此时,5 号同学插入 4 号的后面,那么链表就会变为:
i | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
nxti | 4 | ? | 0 | ? | ? |
此时 2 4 号的位置发送变化,我们一个一个的分析:
- 2 号的后面没有影响,所以 2 号的后面依旧是 3 号;
- 5 号插到了 4 号的后面,所以 5 号的后面将会是原本 4 号后面的人,所以 5 号的后面为 2 号;
- 4 号的后面插进了一个 5 号,所以 4 号的后面变为 5 号。
所以整个链表变为:
i | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
nxti | 4 | 3 | 0 | 5 | 2 |
所以用代码实现是这样:
这时,2 号同学离开了队伍,那么又会发送什么?
那么链表会变为:
i | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
nxti | 4 | before 3before 3 | 0 | 5 | ? |
- 5 号的后面原本是 2 号,但是 2 号离开了,2 号原本的后面是 3 号,所以 5 号的后面变为了 3 号。
所以变为:
i | 1 | 3 | 4 | 5 |
---|---|---|---|---|
nxti | 4 | 0 | 5 | 3 |
改进:
我们可以用结构体减少内存。
原链表为:
i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
ai | 9 | 7 | 0 | 4 |
浪费了很多的空间。
我们可以使用结构体:
i | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
node.valnodei.val | 11 | 44 | 77 | 99 | |
node.nxtnodei.nxt | 44 | 33 | 00 | 22 |
#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;
}