码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1171 并查集优化顺序枚举 | 线段树套单调队列

时间:2015-06-13 18:28:06      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:

 

详见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 }
View Code

 

bzoj 1171 并查集优化顺序枚举 | 线段树套单调队列

标签:

原文地址:http://www.cnblogs.com/idy002/p/4573846.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!