Logo S08577 的博客

博客

[ABC344E] Insert or Erase 题解

...
S08577
2025-12-01 12:57:29

本文章由 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];
    
    }
    
}

这道题是一道练习链表很好的题目。

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。