zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    June. 26th 2018, Week 26th. Tuesday
    June. 25th 2018, Week 26th. Monday
    June. 24th 2018, Week 26th. Sunday
    June. 23rd 2018, Week 25th. Saturday
    June. 22 2018, Week 25th. Friday
    June. 21 2018, Week 25th. Thursday
    June. 20 2018, Week 25th. Wednesday
    【2018.10.11 C与C++基础】C Preprocessor的功能及缺陷(草稿)
    June.19 2018, Week 25th Tuesday
    June 18. 2018, Week 25th. Monday
  • 原文地址:https://www.cnblogs.com/idy002/p/4573846.html
Copyright © 2011-2022 走看看