0w1

ABC 040 D - 道路の老朽化対策について ( Union Find )

D: 道路の老朽化対策について - AtCoder Beginner Contest 040 | AtCoder
最初はパッとしなっかったけど、よく考えると、年について、クエリと辺をソートすると Union Find の問題になる。
Union Find 系の特徴はやはりこういう者だなと思った。
破壊を逆から見て構築にしたり、順番がバラバラな者をソートして一方に増えるものにするなど。
大きい年から小さい年へクエリを処理する。その年より大きい辺をいれる。Union Find で size も記録する。

typedef int T_triplet;
struct triplet{
    T_triplet first, second, third;
    triplet(){}
    triplet( T_triplet _f, T_triplet _s, T_triplet _t ){
        first = _f, second = _s, third = _t;
    }
    bool operator < ( const triplet &oth ) const{
        if( first != oth.first ) return first < oth.first;
        if( second != oth.second ) return second < oth.second;
        return third < oth.third;
    }
};
 
struct UnionFind{
    vi fa, size;
    UnionFind( int sz ){
        fa.resize( sz );
        size.resize( sz );
        for( int i = 0; i < sz; ++i )
            fa[ i ] = i,
            size[ i ] = 1;
    }
    int find( int x ){
        return fa[ x ] == x ? x : fa[ x ] = find( fa[ x ] );
    }
    bool same( int x, int y ){
        int a = find( x );
        int b = find( y );
        return a == b;
    }
    bool unite( int x, int y ){
        int a = find( x );
        int b = find( y );
        if( a == b ) return false;
        size[ b ] += size[ a ];
        fa[ a ] = b; return true;
    }
};
 
const int MAXN = 1e5 + 5;
const int MAXM = 2e5 + 5;
const int MAXY = 2e5 + 5;
const int MAXQ = 1e5 + 5;
const int MAXW = 2e5 + 5;
 
int N, M;
triplet edge[ MAXM ];
int Q;
triplet qry[ MAXQ ];
 
void solve(){
    cin >> N >> M;
    for( int i = 0; i < M; ++i ){
        cin >> edge[ i ].second >> edge[ i ].third >> edge[ i ].first;
        --edge[ i ].second;
        --edge[ i ].third;
    }
    priority_queue< triplet > pq;
    for( int i = 0; i < M; ++i )
        pq.push( edge[ i ] );
 
    cin >> Q;
    for( int i = 0; i < Q; ++i ){
        int u, y; cin >> u >> y;
        --u;
        qry[ i ] = triplet( y, u, i );
    }
    sort( qry, qry + Q );
 
    UnionFind uf = UnionFind( N );
 
    vi ans( Q );
    for( int i = Q - 1; i >= 0; --i ){
        while( !pq.empty() and pq.top().first > qry[ i ].first ){
            uf.unite( pq.top().second, pq.top().third );
            pq.pop();
        }
        ans[ qry[ i ].third ] = uf.size[ uf.find( qry[ i ].second ) ];
    }
 
    for( int i = 0; i < Q; ++i )
        cout << ans[ i ] << endl;
}