详见vfleaking在discuss里的题解.
收获: 当我们要顺序枚举一个序列,并且跳过某些元素,那么我们可以用并查集将要跳过的元素合并到一起,这样当一长串元素需要跳过时,可以O(1)跳过.
暴力:
1 /************************************************************** 2 Problem: 1171 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:1908 ms 7 Memory:6732 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #define min(a,b) ((a)<(b)?(a):(b)) 13 #define max(a,b) ((a)>(b)?(a):(b)) 14 #define oo 0x3f3f3f3f 15 #define N 250010 16 17 int n, L; 18 int x[N], y[N], d[N]; 19 int dp[N], fa[N], qu[N], bg, ed; 20 21 int find( int i ) { 22 return i==fa[i] ? i : fa[i]=find(fa[i]); 23 } 24 int main() { 25 scanf( "%d%d", &n, &L ); 26 d[1] = 0; 27 x[1] = 0; 28 y[1] = 2000000000; 29 for( int i=2; i<=n; i++ ) 30 scanf( "%d%d%d", x+i, y+i, d+i ); 31 for( int i=1; i<=n; i++ ) 32 fa[i] = i; 33 memset( dp, 0x3f, sizeof(dp) ); 34 35 dp[1] = 0; 36 qu[bg=ed=1] = 1; 37 while( bg<=ed ) { 38 int i=qu[bg++]; 39 for( int j=find(i)+1; j<=n && d[j]-d[i]<=L; j=find(j)+1 ) { 40 if( dp[j]!=oo ) continue; 41 int xx = max( x[i], x[j] ); 42 int yy = min( y[i], y[j] ); 43 if( xx<=yy ) { 44 dp[j] = dp[i]+1; 45 qu[++ed] = j; 46 if( dp[j-1]!=oo ) fa[j-1]=j; 47 if( dp[j+1]!=oo ) fa[j]=j+1; 48 } 49 } 50 } 51 for( int i=2; i<=n; i++ ) 52 printf( "%d\n", dp[i]==oo ? -1 : dp[i] ); 53 }
时间: 2024-10-12 14:10:48