1 条题解

  • 1
    @ 2025-10-14 19:37:36

    一开始所有元素都在链表中,比如 n=5n = 5 是这样子的:

    这个 00 号节点是为了方便后续输出剩余链表以及判断是否为空链表表用的(因为是我们自己添加的虚拟节点,所以肯定不会被删除)。用数组来模拟这个双向链表, nex[i]nex[i] 表示 ii 号节点的下一个节点, las[i]las[i] 表示 ii 号节点的上一个节点,那么链表首个节点就是 nex[0]nex[0],因为有 00 号节点的存在,指向为空可以赋值为 1-1 。初始化就可以写成这样:

    int n,m;
    cin >> n >> m;
    for(int i = 0;i<=n;i++){
        nex[i] = i+1;
        las[i] = i-1;
    }
    nex[n] = -1;
    

    注意对于 00 号节点的初始化,以及末尾节点的后继指针模拟为 1-1

    然后先来看一下最简单的删除 xx 号节点的操作,如果xx 号节点的上一个是 ll ,下一个是 rr ,那么删除操作就是让 ll 的后继指向 rrrr 的前继指针指向 ll ,但是要注意 rr 有可能等于 1-1 不存在,这种情况不能访问 las[r]las[r] 。最后别忘了把 nex[x]las[x]nex[x] 和las[x] 赋值为-1,因为我们在删除 xx 节点之前还需要判断一下它是否已经被删了(题目要求这时忽略这条指令),那么写成函数就是:

    void del(int x){
        if(las[x] == -1)return;//已经被删了,函数直接返回
        int l = las[x];
        int r = nex[x];
        nex[l] = r;
        if(r != -1)las[r] = l;
        nex[x] = las[x] = -1;
    }
    

    再来看一下第二种插入操作,把 xx 插入到 yy 的右边,我们得考虑到 xx 可能原本就已经存在于链表中了,那么我们就需要先把 xx 从原来的链表中删除,这个简单,调用一下刚刚的删除函数 del(x)del(x) 就行。插入到 yy 的右边需要先知道 yy 右边是谁,比如说我们叫做 rr , 那么接下来就是改变四个指针的方向了——nex[y],las[r],nex[x],las[x]nex[y],las[r],nex[x],las[x] 。但同样的需要注意 rr 是有可能等于 1-1 不存在的,这个时候不能直接访问 las[r]las[r] ,以及当 x==yx==y 的时候忽略当前指令(题目要求),写成函数就是

    void insert(int x, int y){
      	if(x == y)return;
      	del(x);
      	//把x插入到y的右边
      	int r = nex[y];
      	nex[y] = x;
      	nex[x] = r;
      	las[x] = y;
      	if(r != -1)las[r] = x;//可能r = -1 
    }
    

    最后看一下第一种插入操作,把 xx 插入到 yy 的左边,如果 yy 左边的元素是 ll ,注意这个 ll 是一定不会等于 1-1 的,因为最左边有 00 号节点(再次体现出来虚拟节点的方便之处),那么实际上等价把 xx 插入到 ll 的右边,然后 l==las[y]l == las[y] ,所以调用一下刚写的插入函数 insert(x,las[y])insert(x,las[y]) 就可以了.

    关于输出的话,有虚拟节点,判断是否为空看一下 nex[0]nex[0] 等不等于 1-1 就行了,然后用一个变量循环访问后继节点,直到等于 1-1

    void print(){
    	if(nex[0] == -1)cout << "Empty!";
    	else{
    		int now = nex[0];
    		while(now != -1){
    			cout << now << " ";
    			now = nex[now];
    		}
    	}
    }
    

    贴一下完整的参考代码

    #include<bits/stdc++.h>
    using namespace std;
    
    int nex[1000005];
    int las[1000005];
    void del(int x){
        if(las[x] == -1)return;//已经被删了,函数直接返回
        int l = las[x];
        int r = nex[x];
        nex[l] = r;
        if(r != -1)las[r] = l;
        nex[x] = las[x] = -1;
    }
    void insert(int x, int y){
      	if(x == y)return;
      	del(x);
      	//把x插入到y的右边
      	int r = nex[y];
      	nex[y] = x;
      	nex[x] = r;
      	las[x] = y;
      	if(r != -1)las[r] = x;//可能r = -1 
    }
    void print(){
    	if(nex[0] == -1)cout << "Empty!";
    	else{
    		int now = nex[0];
    		while(now != -1){
    			cout << now << " ";
    			now = nex[now];
    		}
    	}
    }
    int main(){
        int n,m;
        cin >> n >> m;
        for(int i = 0;i<=n;i++)
        {
          	nex[i] = i+1;
          	las[i] = i-1;
      	}
      	nex[n] = -1;
      	while(m--){
        		int opt;
        		cin >> opt;
        		if(opt == 1){
          			int x,y;
          			cin >> x >> y;
          			insert(x,las[y]);
        		}
        		else if(opt == 2){
          			int x,y;
          			cin >> x >> y;
          			insert(x,y);	
        		}
        		else{
          			int x;
          			cin >> x;
          			del(x);
        		}
      	}
      	print();
        return 0;
    }
    /*
    10 10
    2 1 1
    2 5 7
    3 3
    1 2 4
    2 8 6
    1 1 6
    1 7 9
    1 4 8
    3 1
    2 4 8
    */
    

    信息

    ID
    185
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    1
    已通过
    1
    上传者