LOJ121 动态图联通性 这个线段树分治啊,Excited !!!

大家都太强辣!!!

没有题解,因为太弱了…
复习一下奇怪的数据结构姿势

# include <bits/stdc++.h>

char In_buf [10000000], *ip ( In_buf ), Out_buf [1000000], *iq ( Out_buf ) ;

# define readIn(_x_)  {\
    while ( isspace ( *ip ) )  ++ ip ;\
    for ( _x_ = -48 + *ip ++ ; isdigit ( *ip ) ; ( _x_ *= 10 ) += *ip ++ - 48 ) ; ++ ip ;\
}

# define N 5010
# define M 500010

class Union_Find_Set  {
    private :
        int fa [N], rk [N], tp ;
        std :: pair < int*, int > st [M << 1] ;
        inline int find ( int x )  {
            while ( x ^ fa [x] )  x = fa [x] ;
            return x ;
        }
    public :
        Union_Find_Set ( )  {  tp = 0 ;  for ( int i = 1 ; i < N ; ++ i )  fa [i] = i, rk [i] = 1 ;  }
        inline int join ( int u, int v )  {
            int fu = find ( u ), fv = find ( v ) ;
            if ( fu == fv )  return 0 ;

            if ( rk [fu] < rk [fv] )  std :: swap ( fu, fv ) ;
            st [++ tp] = std :: make_pair ( fa + fv, fa [fv] ) ;
            fa [fv] = fu ;
            st [++ tp] = std :: make_pair ( rk + fu, rk [fu] ) ;
            ++ rk [fu] ;

            return 2 ;
        }

        inline bool query ( int u, int v )  {
            return find ( u ) == find ( v ) ;
        }

        inline void undo ( )  {
            *st [tp].first = st [tp].second ;  -- tp ;
        }
} T ;

bool isquery [M] ;
std :: pair < int, int > query_staff [M] ;
std :: vector < std :: pair < int, int > > v [M << 2] ;
std :: map < std :: pair < int, int >, int > exist_time ;

inline void Insert ( int o, int l, int r, const int b, const int e, const std :: pair < int, int > edge )  {
    if ( b <= l && r <= e )  return v [o].emplace_back ( edge ) ;
    int mid = ( l + r ) >> 1 ;
    if ( b <= mid )  Insert ( o << 1, l, mid, b, e, edge ) ;
    if ( e > mid )  Insert ( o << 1 | 1, mid + 1, r, b, e, edge ) ;
}

inline void Solve ( int o, int l, int r )  {
    int tp ( 0 ) ;
    for ( auto& p : v [o] )  tp += T.join ( p.first, p.second ) ;
    if ( l == r )  {
        if ( isquery [l] )  *iq ++ = ( T.query ( query_staff [l].first, query_staff [l].second ) ? 'Y' : 'N' ), *iq ++ = '\n' ;
    }  else  {
        int mid = ( l + r ) >> 1 ;
        Solve ( o << 1, l, mid ), Solve ( o << 1 | 1, mid + 1, r ) ;
    }
    while ( tp -- )  T.undo ( ) ;
}

int main ( )  {

    fread ( In_buf, 1, 10000000, stdin ) ;

    int n, m ;
    readIn ( n ) ; readIn ( m ) ;
    for ( int i = 1 ; i <= m ; ++ i )  {
        static int opt, u, v ;
        readIn ( opt ) ; readIn ( u ) ;  readIn ( v ) ;
        if ( u > v )  std :: swap ( u, v ) ;
        if ( opt == 0 )  {
            exist_time [std :: make_pair ( u, v )] = i ;
        }  else  {
            if ( opt == 1 )  {
                Insert ( 1, 1, m, exist_time [std :: make_pair ( u, v )], i, std :: make_pair ( u, v ) ) ;
                exist_time.erase ( std :: make_pair ( u, v ) ) ;
            }  else  {
                isquery [i] = 1 ;
                query_staff [i] = std :: make_pair ( u, v ) ;
            }
        }
    }

    for ( auto& p : exist_time )  Insert ( 1, 1, m, p.second, m, p.first ) ;

//  exist_time.clear ( ) ;
    Solve ( 1, 1, m ) ;

    fwrite ( Out_buf, iq - Out_buf, 1, stdout ) ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值