大家都很强, 可与之共勉 。
题意:
您有
n(n≤2e5)
个点,以一个
pair(x,y)
给出,表示横纵坐标
(0≤x,y≤1e9)
。求从
1
号点到
题解:
其实很早之前就做了这道题,大约是在
7
月的
于是重新来写一下,顺便(滑稽)搞一波完全大封装。
考虑朴素的连边方案。有
O(n2)
条边,好刺激吖。但是我们发现这里面的很多边其实是有个卵用的。举个栗子:
1−>2,2−>3,1−>3
当
1,2,3
之间的距离都是由
x
或
所以我们分类讨论,考虑是按什么为关键字计算距离,于是关于
x
与
然后点
a
向后继连边,代价为当前关键字之差绝对值。
这样是
然后直接上
Dijkstra
就好啦。
封装真好玩,可是好慢啊
/**************************************************************
Problem: 4152
User: Lazer2001
Language: C++
Result: Accepted
Time:4012 ms
Memory:36064 kb
****************************************************************/
# include <bits/stdc++.h>
namespace In {
# define In_Len 6000000
static std :: streambuf *fb ( std :: cin.rdbuf ( ) ) ;
static char buf [In_Len], *ss ( 0 ) ;
void init ( ) { fb -> sgetn ( ss = buf, In_Len ) ; }
inline int read ( ) {
register int x ;
bool opt ( 1 ) ;
while ( isspace ( *ss ) ) ++ ss ;
if ( *ss == 45 ) { ++ ss ; opt = 0 ; }
for ( x = -48 + *ss ; isdigit ( * ++ ss ) ; ( x *= 10 ) += *ss - 48 ) ; ++ ss ;
return opt ? x : -x ;
}
# undef pick
# undef In_Len
}
template < class T > inline bool chkmin ( T& d, const T& x ) { return ( d > x ) ? ( d = x ), 1 : 0 ; }
template < class T, int N >
class Heap {
private :
int len ;
T a [N] ;
public :
Heap ( ) { len = 0 ; }
inline void push ( const T& ele ) {
a [++ len] = ele ;
std :: push_heap ( a + 1, a + 1 + len, std :: greater < T > ( ) ) ;
}
inline void pop ( ) {
std :: pop_heap ( a + 1, a + 1 + len --, std :: greater < T > ( ) ) ;
}
inline bool empty ( ) {
return len == 0 ;
}
inline T top ( ) {
return a [1] ;
}
} ;
template < int N >
class Dijkstra {
private :
struct edge {
int to, w ; edge* nxt ;
} g [N << 2], *head [N], *cur ;
int dis [N] ;
Heap < std :: pair < int, int >, N * 10 > Q ;
public :
Dijkstra ( ) { cur = g ; }
inline void add_edge ( int u, int v, int w, bool db = 1 ) {
*cur = ( edge ) { v, w, head [u] } ; head [u] = cur ++ ;
if ( db ) add_edge ( v, u, w, 0 ) ;
}
inline int dijkstra ( int S, int T ) {
memset ( dis, 0x3f, sizeof dis ) ;
Q.push ( std :: make_pair ( dis [S] = 0, S ) ) ;
while ( ! Q.empty ( ) ) {
int u = Q.top ( ).second ; Q.pop ( ) ;
for ( edge* it = head [u] ; it ; it = it -> nxt )
if ( chkmin ( dis [it -> to], dis [u] + it -> w ) ) {
Q.push ( std :: make_pair ( dis [it -> to], it -> to ) ) ;
}
}
return dis [T] ;
}
} ;
Dijkstra < 200010 > Gp ;
template < class T1, class T2 >
struct cmp_x {
inline bool operator ( ) ( const std :: pair < T1, T2 >& a, const std :: pair < T1, T2 >& b ) {
return a.first < b.first ;
}
} ;
template < class T1, class T2 >
struct cmp_y {
inline bool operator ( ) ( const std :: pair < T1, T2 >& a, const std :: pair < T1, T2 >& b ) {
return a.second < b.second ;
}
} ;
std :: pair < int, std :: pair < int, int > > p [200010] ;
int main ( ) {
In :: init ( ) ;
int n ;
n = In :: read ( ) ;
for ( int i = 1 ; i <= n ; ++ i ) {
static int x, y ;
x = In :: read ( ), y = In :: read ( ) ;
p [i] = std :: make_pair ( x, std :: make_pair ( y, i ) ) ;
}
std :: sort ( p + 1, p + 1 + n, cmp_x < int, std :: pair < int, int > > ( ) ) ;
for ( int i = 1 ; i < n ; ++ i ) {
Gp.add_edge ( p [i].second.second, p [i + 1].second.second, p [i + 1].first - p [i].first ) ;
}
std :: sort ( p + 1, p + 1 + n, cmp_y < int, std :: pair < int, int > > ( ) ) ;
for ( int i = 1 ; i < n ; ++ i ) {
Gp.add_edge ( p [i].second.second, p [i + 1].second.second, p [i + 1].second.first - p [i].second.first ) ;
}
printf ( "%d\n", Gp.dijkstra ( 1, n ) ) ;
return 0 ;
}