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

详见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
", dp[i]==oo ? -1 : dp[i] );
53 }
View Code

线段树套单调队列:

 1 #include <cstdio>
 2 #include <list>
 3 #include <algorithm>
 4 #define N 250010
 5 #define oo 0x3f3f3f3f
 6 using namespace std;
 7 
 8 struct Pair {
 9     int d, v;
10     Pair( int d, int v ):d(d),v(v){}
11 };
12 struct Queue {
13     list<Pair> q;
14     void push( const Pair &p ) {
15         while( !q.empty() && q.back().v >= p.v ) q.pop_back();
16         q.push_back( p );
17     }
18     int pop( int d ) {
19         while( !q.empty() && q.front().d<d ) q.pop_front();
20         return q.empty() ? oo : q.front().v;
21     }
22 };
23 struct Node {
24     Queue qa, qb;
25     int lf, rg;
26     Node *ls, *rs;
27     void modify( int L, int R, const Pair &p ) {
28         qb.push(p);
29         if( L<=lf && rg<=R ) {
30             qa.push(p);
31             return;
32         }
33         int mid=(lf+rg)>>1;
34         if( L<=mid ) ls->modify(L,R,p);
35         if( R>mid ) rs->modify(L,R,p);
36     }
37     int query( int L, int R, int d ) {
38         if( L<=lf && rg<=R ) return qb.pop(d);
39         int rt = qa.pop(d);
40         int mid=(lf+rg)>>1;
41         if( L<=mid ) {
42             int t = ls->query(L,R,d);
43             rt = min( rt, t );
44         }
45         if( R>mid ) {
46             int t = rs->query(L,R,d);
47             rt = min( rt, t );
48         }
49         return rt;
50     }
51 }pool[N*2*3], *tail=pool, *root;
52 
53 int n, L;
54 int x[N], y[N], d[N];
55 int disc[N*2], dtot;
56 
57 Node *build( int lf, int rg ) {
58     Node *nd = ++tail;
59     nd->lf=lf, nd->rg=rg;
60     if( lf==rg ) {
61         return nd;
62     } else {
63         int mid=(lf+rg)>>1;
64         nd->ls = build( lf, mid );
65         nd->rs = build( mid+1, rg );
66         return nd;
67     }
68 }
69 int main() {
70     scanf( "%d%d", &n, &L );
71     x[1] = 0;
72     y[1] = 2000000000;
73     disc[++dtot] = x[1];
74     disc[++dtot] = y[1];
75     d[1] = 0;
76     for( int i=2; i<=n; i++ ) {
77         scanf( "%d%d%d", x+i, y+i, d+i );
78         disc[++dtot] = x[i];
79         disc[++dtot] = y[i];
80     }
81     sort( disc+1, disc+1+dtot );
82     dtot = unique( disc+1, disc+1+dtot ) - disc - 1;
83     for( int i=1; i<=n; i++ ) {
84         x[i] = lower_bound( disc+1, disc+1+dtot, x[i] ) - disc;
85         y[i] = lower_bound( disc+1, disc+1+dtot, y[i] ) - disc;
86     }
87     root = build( 1, dtot );
88     root->modify( x[1], y[1], Pair(0,0) );
89     for( int i=2; i<=n; i++ ) {
90         int ans = root->query( x[i], y[i], d[i]-L );
91         if( ans==oo ) {
92             printf( "-1
" );
93         } else {
94             ans++;
95             printf( "%d
", ans );
96             root->modify( x[i], y[i], Pair(d[i],ans) );
97         }
98     }
99 }
View Code
原文地址:https://www.cnblogs.com/idy002/p/4573846.html