概念
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。(百度)
操作(以下红边为新加入的边,黑边为删除的边)
题外话- -由于窝不会用链表,所以才用数组实现的
用一个pre数组存储每一个节点的前驱(即前一个节点),next数组存储每一个节点的后驱(即后一个节点)。
删点
现在要将x节点删掉(如下图)。我们知道了x = pre [z] = next [y] , y = pre[x] , z = next[x]
。其实只用将 y 节点的 next(即y的后驱) 改为 z ,和 z 节点的 pre(即z的前驱) 改为 y 即可。
代码:
int a=pre[x],b=next[x];
next[a]=b,pre[b]=a;
加点
现在要将x加到y和z之间(如下图)。我们知道了y = pre[z] , z = next[y] 。现在要将 y 的 next(即y的后驱) 修改为 x ,将 z 的 pre(即z的前驱) 改为 x , 将新加入的x的pre(前驱)记录为y,next(后驱)记录为z即可。
代码:
next[y]=x,pre[z]=z;
pre[x]=y,next[x]=z;
例题:开车旅行
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
int read(){
int s=0,v=1;
char c=getchar();
while(c>'9'||c<'0'){
if(c=='-') v=-1;
c=getchar();
}
while(c>='0'&&c<='9') s=s*10+c-'0',c=getchar();
return s*v;
}
struct City{
int h,bh;
bool operator <(const City&rhs)const{
return h<rhs.h;
}
}city[100005];
int n,m,s,s0,h,H[100005],pre[100005],nex[100005],min1[100005],min2[100005],loc[100005];
ll st[2][2][100005][20];
double bi=1e15;
void work(int x,int w){
if(pre[w]) min1[x]=city[pre[w]].bh;
if(!pre[w]||nex[w]<=n&&city[w].h-city[pre[w]].h>city[nex[w]]