Official

D - Play Train Editorial by sugarrr


それぞれの電車について、

  • 自分の前部に連結している電車の番号
  • 自分の後部に連結している電車の番号

\(2\) つの値を管理すれば良いです。

\(c_i = 1,2\) のクエリについて、上記の値の更新は \(O(1)\) で行えます。
\(c_i = 3\) のクエリについて、「出力する電車の番号の個数の合計は \(10^6\) 以下」という条件から、愚直に実装して間に合います。

以上でこの問題を解くことができました。

C++の実装例を示します。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

signed main(){
    ll n,q;cin>>n>>q;
    ll nil=-1;
    vector<ll>front(n+1,nil); // front[i] := 電車iの前部に連結している電車。ないならnil。
    vector<ll>back(n+1,nil);  // back[i]  := 電車iの後部に連結している電車。ないならnil。
    while(q--){
        ll c;cin>>c;
        if(c==1){
            ll x,y;cin>>x>>y;
            back[x] = y;
            front[y] = x;
        }else if(c==2){
            ll x,y;cin>>x>>y;
            back[x] = nil;
            front[y] = nil;
        }else{
            ll x;cin>>x;
            while(front[x] != nil){
                x = front[x]; // xの連結成分の、先頭に移動
            }
            vector<ll>ans;
            while(x != nil){
                ans.push_back(x);
                x = back[x];
            }
            cout<<ans.size()<<" ";
            for(ll i=0;i<=(int)ans.size()-1;i++){
                cout<<ans[i];
                if(i!=(int)ans.size()-1)cout<<" ";
                else cout<<endl;
            }
        }
    }

    return 0;
}

posted:
last update: