本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-03-14 19:45:05
六个字:难想,难写,难调
我们一看插入和删除就知道用链表,可是现在几乎没有人用链表 (我忘了) ,于是我就用数组模拟指针,定义 $l$ 数组存这个数左边是哪个数,$r$ 数组存这个数右边是哪个数。
初始化不必多说,就在最后用 $r$ 数组存上 $-1145$。
根据链表的原理,我们要添加一个数,就是让这个数前面后面的链改变一下,就像下图

根据此图,我们可以修改一下我们的数组。
$$l_5=1 $$ $$l_4=5 $$ $$r_1=5 $$ $$r_5=4 $$
这一部分写成代码较为困难,涉及到许多转化,自己在草稿纸上手写几遍再多看看代码就明白了。
if(op==1){
cin>>x>>y;
l[r[x]]=y;
l[y]=x;
int d=r[x];
r[l[y]]=y;
r[y]=d;
}
删除相对简单一点,我们只需要把连着要删除数字的链连上前面的或后面的。 这样说可能不清楚,可参考下图,再看看代码就能理解。

else{
cin>>x;
int L=l[x];
int R=r[x];
l[R]=l[x];
r[L]=r[x];
}
最后就是输出了,我们在 $r$ 的最后放了一个 $-1145$,就是为了输出什么时候到达终点。
int tot=0;
while(r[tot]!=-1145){
\/\/cout<<tot<<" ";
cout<<r[tot]<<" ";
tot=r[tot];
}
代码
#include<iostream>
#include<queue>
#include<algorithm>
#include<map>
#define int long long
using namespace std;
const int N=2e6+5;
int a[N];
\/\/int l[N],r[N];\/\/左指针数组,右指针数组
map<int,int> l,r;
signed main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
l[a[i]]=a[i-1];
r[a[i-1]]=a[i];
}
r[a[n]]=-1145;
int T;
cin>>T;
while(T--){
int op,x,y;
cin>>op;
if(op==1){
cin>>x>>y;
l[r[x]]=y;
l[y]=x;
int d=r[x];
r[l[y]]=y;
r[y]=d;
}
else{
cin>>x;
int L=l[x];
int R=r[x];
l[R]=l[x];
r[L]=r[x];
}
}
int tot=0;
while(r[tot]!=-1145){
\/\/cout<<tot<<" ";
cout<<r[tot]<<" ";
tot=r[tot];
}
}
这道题是一道练习链表很好的题目。

鲁ICP备2025150228号