[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=3387
[算法]
f[i][0]表示从第i个栅栏的左端点走到原点的最少移动步数
f[i][1]表示从第i个栅栏的右端点走到原点的最少移动步数
我们可以用线段树优化转移
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 50010 const int V = 100010; struct info { int x,y; } a[MAXN]; int i,N,S,x,y; int f[MAXN][2]; struct SegmentTree { struct Node { int l,r; int mx,tag; } Tree[V << 4]; inline void build(int index,int l,int r) { int mid; Tree[index].l = l; Tree[index].r = r; Tree[index].mx = Tree[index].tag = 0; if (l == r) return; mid = (l + r) >> 1; build(index << 1,l,mid); build(index << 1 | 1,mid + 1,r); } inline void pushdown(int index) { if (Tree[index].tag) { Tree[index << 1].mx = max(Tree[index << 1].mx,Tree[index].tag); Tree[index << 1 | 1].mx = max(Tree[index << 1 | 1].mx,Tree[index].tag); Tree[index << 1].tag = max(Tree[index << 1].tag,Tree[index].tag); Tree[index << 1 | 1].tag = max(Tree[index << 1 | 1].tag,Tree[index].tag); Tree[index].tag = 0; } } inline void modify(int index,int l,int r,int val) { int mid; if (Tree[index].l == l && Tree[index].r == r) { Tree[index].mx = Tree[index].tag = val; return; } pushdown(index); mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= r) modify(index << 1,l,r,val); else if (mid + 1 <= l) modify(index << 1 | 1,l,r,val); else { modify(index << 1,l,mid,val); modify(index << 1 | 1,mid + 1,r,val); } } inline int query(int index,int pos) { int mid; if (Tree[index].l == Tree[index].r) return Tree[index].mx; pushdown(index); mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= pos) return query(index << 1,pos); else return query(index << 1 | 1,pos); } } T; int main() { scanf("%d%d",&N,&S); S += V; for (i = 1; i <= N; i++) { scanf("%d%d",&a[i].x,&a[i].y); a[i].x += V; a[i].y += V; } T.build(1,1,V << 1); f[0][0] = f[0][1] = 0; a[0].x = a[0].y = V; for (i = 1; i <= N; i++) { x = T.query(1,a[i].x); y = T.query(1,a[i].y); f[i][0] = min(f[x][0] + abs(a[i].x - a[x].x),f[x][1] + abs(a[i].x - a[x].y)); f[i][1] = min(f[y][0] + abs(a[i].y - a[y].x),f[y][1] + abs(a[i].y - a[y].y)); T.modify(1,a[i].x,a[i].y,i); } printf("%d ",min(abs(S - a[N].x) + f[N][0],abs(S - a[N].y) + f[N][1])); return 0; }