Problem:
G: 一番遠い町
問題文
$N$ 個の町と $N-1$ 個の道があります。
すべての町と道にはそれぞれ $1$ から $N$, $1$ から $N-1$ の番号がついています。
道 $i$ は町 $a_i$ と町 $b_i$ を距離 $d_i$ で双方向につないでいます。
最初はすべての道が通行可能な状態であり、どの町からもいくつかの道を通ることですべての町に行くことができます。
すいばかくんは最初、町 $1$ にいます。
$Q$ 個のクエリが与えられるので順番に処理してください。クエリは $3$ 種類あり、以下の形式で与えられます。
クエリ $1$ :
1 x
― すいばかくんが町 $x$ に移動する。ただし、このクエリ時点で、すいばかくんがいる町と町 $x$ は通行可能な $1$ つの道で直接つながれていることが保証される。
クエリ $2$ :
2 y
― 道 $y$ が封鎖される。ただし、このクエリ時点で、道 $y$ は通行可能であることが保証される。
クエリ $3$ :
3 z
― 道 $z$ が通行可能になる。ただし、このクエリ時点で、道 $z$ は封鎖されていることが保証される。
さらに、各クエリを行った直後に、すいばかくんがその時点で通行可能な道のみを使って到達可能な町のうち、すいばかくんがいる町から一番遠い町の番号を昇順ですべて出力してください。
制約
$1 \leq N \leq 2 \times 10^5$
$1 \leq a_i, b_i \leq N$, $a_i \neq b_i$
$1 \leq d_i \leq 10^6$
$1 \leq Q \leq 2 \times 10^5$
クエリ $1$ において、$1 \leq x \leq N$ を満たす。また、このクエリ時点で、すいばかくんがいる町と町 $x$ は通行可能な $1$ つの道で直接つながれている。
クエリ $2$ において、$1 \leq y \leq N-1$ を満たす。また、このクエリ時点で、道 $y$ は通行可能である。
クエリ $3$ において、$1 \leq z \leq N-1$ を満たす。また、このクエリ時点で、道 $z$ は封鎖されている。
$i$ 番目のクエリで出力すべき町の個数を $c_i$ とするとき、$\sum_{i=1}^{Q}c_i \leq 4 \times 10^5$ を満たす。
入力はすべて整数である。
入力
以下の形式で標準入力から与えられる。
$N$
$a_1$ $b_1$ $d_1$
$a_2$ $b_2$ $d_2$
$:$
$a_{N-1}$ $b_{N-1}$ $d_{N-1}$
$Q$
$Query_1$
$Query_2$
$:$
$Query_Q$
$Query_i$ は問題文にある $3$ 種類のクエリのいずれかの形式で与えらえる。
出力
$Q$ 行出力せよ。
$i$ 行目には、$i$ 番目クエリ後の出力すべき町の番号が昇順で $v_1$, $v_2$, $...$, $v_c$ の $c$ 個であるとき、以下のように空白区切りで出力せよ。
$c$ $v_1$ $v_2$ $...$ $v_c$
入力例 1
6
2 4 1
1 2 1
4 6 1
2 3 1
4 5 1
5
2 5
2 3
1 2
3 5
1 4
出力例 1
1 6
2 3 4
3 1 3 4
1 5
2 1 3
$1$ つ目のクエリで、道 $5$ が封鎖されます。この直後に、すいばかくんが到達可能な町は $1$, $2$, $3$, $4$, $6$ であり、すいばかくんがいる町 $1$ からの距離はそれぞれ $0$, $1$, $2$, $2$, $3$ なので、答えは町 $6$ になります。
$2$ つ目のクエリで、道 $3$ が封鎖されます。この直後に、すいばかくんが到達可能な町は $1$, $2$, $3$, $4$ であり、すいばかくんがいる町 $1$ からの距離はそれぞれ $0$, $1$, $2$, $2$ なので、答えは町 $3$, $4$ になります。
$3$ つ目のクエリで、すいばかくんは町 $2$ に移動します。この直後に、すいばかくんが到達可能な町は $1$, $2$, $3$, $4$ であり、すいばかくんがいる町 $2$ からの距離はそれぞれ $1$, $0$, $1$, $1$ なので、答えは町 $1$, $3$, $4$ になります。
$4$ つ目のクエリで、道 $5$ が通行可能になります。この直後に、すいばかくんが到達可能な町は $1$, $2$, $3$, $4$, $5$ であり、すいばかくんがいる町 $2$ からの距離はそれぞれ $1$, $0$, $1$, $1$, $2$ なので、答えは町 $5$ になります。
$5$ つ目のクエリで、すいばかくんは町 $4$ に移動します。この直後に、すいばかくんが到達可能な町は $1$, $2$, $3$, $4$, $5$ であり、すいばかくんがいる町 $4$ からの距離はそれぞれ $2$, $1$, $2$, $0$, $1$ なので、答えは町 $1$, $3$ になります。
入力例 2
5
3 4 1
2 1 1
4 5 1
3 2 1
6
2 2
3 2
1 2
1 3
2 4
1 4
出力例 2
1 1
1 5
1 5
2 1 5
1 5
2 3 5

Submitted solutions:

code_snippet: // verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3143

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

#define call_from_test
template<typename Vertex, typename Cluster, size_t N>
struct TopTree{
  enum Type { Compress, Rake, Edge };
  struct Node{
    Vertex* vs[2];
    Cluster dat;
    Node* p;
    Node* q;
    Node* ch[2];
    bool rev,guard;
    Type type;
    Node():p(nullptr),q(nullptr),rev(false),guard(false){}
  };

  inline static array<Vertex, 2*N> pool_vertex;
  inline static size_t ptr_vertex = 0;

  inline static array<Node, 4*N> pool_node;
  inline static size_t ptr_node = 0;

  Cluster id;

  template<typename ...Args>
  inline Vertex* create(Args ...args){
    auto t=&pool_vertex[ptr_vertex++];
    auto dummy=&pool_vertex[ptr_vertex++];
    *t=Vertex(forward<Args>(args)...);
    link(t,id,dummy);
    return t;
  }

  Node* recycle=nullptr;
  inline void dispose_node(Node* t){
    t->p=recycle;
    recycle=t;
  }

  inline Node* get_new_node(){
    if(recycle) return new(exchange(recycle,recycle->p)) Node;
    return &(pool_node[ptr_node++]);
  }

  inline Node* edge(Vertex* u,Cluster w,Vertex* v){
    auto t=get_new_node();
    t->vs[0]=u;t->vs[1]=v;t->dat=w;t->type=Type::Edge;
    return pushup(t);
  }

  inline Node* compress(Node* l,Node* r){
    auto t=get_new_node();
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Compress;
    return pushup(t);
  }

  inline Node* rake(Node* l,Node* r){
    auto t=get_new_node();
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Rake;
    return pushup(t);
  }

  int parent_dir(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->guard) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  int parent_dir_ignore_guard(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  inline Node* pushup(Node* const t){
    Node* const l=t->ch[0];
    Node* const r=t->ch[1];

    if(t->type==Type::Compress){
      assert(l->vs[1]==r->vs[0]);
      t->vs[0]=l->vs[0];
      t->vs[1]=r->vs[1];

      Cluster lf=l->dat;
      if(t->q){
        assert(l->vs[1]==t->q->vs[1]);
        lf=Cluster::rake(l->dat,t->q->dat);
      }
      t->dat=Cluster::compress(lf,r->vs[0],r->dat);

      l->vs[1]->handle=t;
    }

    if(t->type==Type::Rake){
      propagate(t);
      assert(l->vs[1]==r->vs[1]);
      t->vs[0]=l->vs[0];
      t->vs[1]=l->vs[1];
      t->dat=Cluster::rake(l->dat,r->dat);
    }else{
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }
    return t;
  }

  inline void toggle(Node* t){
    if(t->type==Type::Edge){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
    }else if(t->type==Type::Compress){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
      t->rev^=true;
    }else if(t->type==Type::Rake){
    }else abort();
  }

  inline void propagate(Node* t){
    if(t->type==Type::Compress){
      if(t->rev){
        assert(t->ch[0] and t->ch[1]);
        swap(t->ch[0],t->ch[1]);
        toggle(t->ch[0]);
        toggle(t->ch[1]);
        t->rev=false;
      }
    }
  }

  void set_toggle(Node* v){
    toggle(v);propagate(v);
  }

  void pushdown(Node* t){
    if(!t) return;
    pushdown(t->p);
    propagate(t);
  }

  void rotate(Node* t,Node* x,size_t dir){
    Node* y=x->p;
    int par=parent_dir_ignore_guard(x);
    propagate(t->ch[dir]);
    x->ch[dir^1]=t->ch[dir];
    t->ch[dir]->p=x;
    t->ch[dir]=x;
    x->p=t;
    t->p=y;
    if(~par) y->ch[par]=t;
    else if(y and y->type==Type::Compress) y->q=t;
    pushup(x);pushup(t);
    if(y and !y->guard) pushup(y);
  }

  void splay(Node* t){
    assert(t->type!=Type::Edge);
    propagate(t);

    while(~parent_dir(t)){
      Node* q=t->p;
      if(q->type!=t->type) break;
      if(~parent_dir(q) and q->p and q->p->type==q->type){
        Node* r=q->p;
        if(r->p) propagate(r->p);
        propagate(r);propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        int rq_dir=parent_dir(q);
        if(rq_dir==qt_dir){
          rotate(q,r,rq_dir^1);
          rotate(t,q,qt_dir^1);
        }else{
          rotate(t,q,qt_dir^1);
          rotate(t,r,rq_dir^1);
        }
      }else{
        if(q->p) propagate(q->p);
        propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        rotate(t,q,qt_dir^1);
      }
    }
  }

  Node* expose(Node* t){
    pushdown(t);
    while(true){
      assert(t->type!=Type::Rake);
      if(t->type==Type::Compress) splay(t);
      Node* n=nullptr;
      {
        Node* p=t->p;
        if(!p) break;
        if(p->type==Type::Rake){
          propagate(p);
          splay(p);
          n=p->p;
        }
        if(p->type==Type::Compress){
          propagate(p);
          if(p->guard and ~parent_dir_ignore_guard(t)) break;
          n=p;
        }
      }
      splay(n);
      int dir=parent_dir_ignore_guard(n);
      if(dir==-1 or n->p->type==Type::Rake) dir=0;

      Node* const c=n->ch[dir];
      if(dir==1){
        set_toggle(c);
        set_toggle(t);
      }
      int n_dir=parent_dir(t);
      if(~n_dir){
        Node* const r=t->p;
        propagate(c);
        propagate(r);
        r->ch[n_dir]=c;
        c->p=r;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(r);pushup(t);pushup(n);
        splay(r);
      }else{
        propagate(c);
        n->q=c;
        c->p=n;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(t);pushup(n);
      }
      if(t->type==Type::Edge) t=n;
    }
    return t;
  }

  Node* expose(Vertex* v){
    return expose((Node*)(v->handle));
  }

  void soft_expose(Vertex* u,Vertex* v){
    pushdown((Node*)u->handle);
    pushdown((Node*)v->handle);
    Node* rt=expose(u);

    if(u->handle==v->handle){
      if(rt->vs[1]==u or rt->vs[0]==v)
        set_toggle(rt);
      return;
    }

    rt->guard=true;
    Node* soft=expose(v);
    rt->guard=false;

    pushup(rt);
    if(parent_dir(soft)==0) set_toggle(rt);
  }

  void bring(Node* rt){
    Node* rk=rt->q;
    if(!rk){
      Node* ll=rt->ch[0];
      dispose_node(ll->p);
      ll->p=nullptr;
      pushup(ll);
    }else if(rk->type==Type::Compress or rk->type==Type::Edge){
      Node* nr=rk;
      set_toggle(nr);
      rt->ch[1]=nr;
      nr->p=rt;
      rt->q=nullptr;

      pushup(nr);pushup(rt);
    }else if(rk->type==Type::Rake){
      propagate(rk);
      while(rk->ch[1]->type==Type::Rake){
        propagate(rk->ch[1]);
        rk=rk->ch[1];
      }
      pushdown(rk);

      rt->guard=true;
      splay(rk);
      rt->guard=false;

      Node* ll=rk->ch[0];
      Node* rr=rk->ch[1];
      propagate(ll);
      set_toggle(rr);

      rt->ch[1]=rr;
      rr->p=rt;

      rt->q=ll;
      ll->p=rt;

      dispose_node(rk);
      pushup(ll);pushup(rr);pushup(rt);
    }
  }

  Node* link(Vertex* u,Cluster w,Vertex* v){
    if(!u->handle and !v->handle) return edge(u,w,v);

    Node* nnu=(Node*)u->handle;
    Node* nnv=(Node*)v->handle;
    Node* ee=edge(u,w,v);
    Node* ll=nullptr;

    assert(nnv);
    Node* vv=expose(nnv);
    propagate(vv);
    if(vv->vs[1]==v) set_toggle(vv);
    if(vv->vs[0]==v){
      Node* nv=compress(ee,vv);
      ee->p=nv;
      pushup(ee);
      vv->p=nv;
      pushup(vv);pushup(nv);
      ll=nv;
    }else{
      Node* nv=vv;
      Node* ch=nv->ch[0];
      propagate(ch);
      nv->ch[0]=ee;
      ee->p=nv;
      pushup(ee);

      Node* bt=nv->q;
      Node* rk=nullptr;
      if(bt){
        propagate(bt);
        rk=rake(bt,ch);
        bt->p=rk;
        ch->p=rk;
        pushup(bt);pushup(ch);
      }else{
        rk=ch;
      }
      nv->q=rk;
      rk->p=nv;
      pushup(rk);pushup(nv);
      ll=nv;
    }

    assert(nnu);
    Node* uu=expose(nnu);
    propagate(uu);
    if(uu->vs[0]==u) set_toggle(uu);
    if(uu->vs[1]==u){
      Node* tp=compress(uu,ll);
      uu->p=tp;
      ll->p=tp;
      pushup(uu);pushup(ll);pushup(tp);
    }else{
      Node* nu=uu;
      Node* ch=nu->ch[1];
      toggle(ch);
      propagate(ch);

      nu->ch[1]=ll;
      ll->p=nu;
      pushup(ll);

      Node* al=nu->q;
      Node* rk=nullptr;
      if(al){
        propagate(al);
        rk=rake(al,ch);
        al->p=rk;
        ch->p=rk;
        pushup(al);pushup(ch);
      }else{
        rk=ch;
      }
      nu->q=rk;
      rk->p=nu;
      pushup(rk);pushup(nu);
    }
    return ee;
  }

  void cut(Vertex* u,Vertex *v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    Node* rr=rt->ch[1];
    rr->p=nullptr;
    set_toggle(rr);
    assert(rr->ch[1]->type==Type::Edge);
    dispose_node(rr->ch[1]);
    bring(rr);bring(rt);
  }

  Node* path(Vertex* u,Vertex* v){
    assert(u!=v);
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    propagate(rt->ch[1]);
    return rt->ch[1]->ch[0];
  }

  void set_vertex(Vertex* u,Vertex v){
    auto t=expose(u);
    *u=v;
    pushup(t);
  }

  void set_edge(Vertex* u,Vertex* v,const Cluster &w){
    auto t=path(u,v);
    assert(t->type==Type::Edge);
    t->dat=w;
    while(t) pushup(t),t=t->p;
  }

  Cluster get_path(Vertex* u,Vertex* v){
    return path(u,v)->dat;
  }

  Cluster get_subtree(Vertex* v){
    return expose(v)->dat;
  }

  // subtree of v when p is root
  Cluster get_subtree(Vertex* p,Vertex* v){
    Node* t=path(p,v);
    Cluster res=t->p->ch[1]->dat;
    res.toggle();
    Node* rk=t->p->q;
    if(t->p->q){
      assert(rk->vs[1]==t->p->ch[1]->vs[0]);
      res=Cluster::rake(res,rk->dat);
    }
    return res;
  }
};

struct Vertex{
  void* handle;
  Vertex():handle(nullptr){}
};

template<typename T>
struct Farthest{
  struct pi{
    T dist;
    int idx;
    pi():dist(0),idx(-1){}
    pi(T dist,int idx):dist(dist),idx(idx){}
    bool operator<(const pi &o)const{return dist<o.dist;}
    pi operator+(const T e)const{return pi(dist+e,idx);}
  };
  pi md,lf,rg;
  T len;
  Farthest():lf(0,-1),rg(0,-1),len(0){}
  Farthest(T d,int f,int t):lf(d,t),rg(d,f),len(d){}
  Farthest(pi md,pi lf,pi rg,T len):md(md),lf(lf),rg(rg),len(len){}
  void toggle(){swap(lf,rg);}
  static Farthest compress(Farthest &x,Vertex*,Farthest &y){
    return Farthest(
      max(x.rg,y.lf),
      max(x.lf,y.lf+x.len),
      max(y.rg,x.rg+y.len),
      x.len+y.len);
  }
  static Farthest rake(Farthest &x,Farthest &y){
    return Farthest(pi(),max(x.lf,y.rg+x.len),max(x.rg,y.rg),x.len);
  }
};

template<typename T, size_t N>
vector<int> get_all_farthests(TopTree<Vertex, Farthest<T>, N> &G,Vertex* v){
  using TT = typename remove_reference<decltype(G)>::type;
  using Node = typename TT::Node;
  using Type = typename TT::Type;
  vector<int> fs;
  auto dist=G.get_subtree(v).md.dist;
  if(dist==T(0)) return {};
  auto dfs=[&](auto dfs,Node* rt,T d,bool left)->void{
    if(!rt) return;
    G.propagate(rt);

    auto cur=left?(rt->dat.lf):(rt->dat.rg);
    if(d+cur.dist!=dist) return;

    if(rt->type==Type::Edge){
      if(~cur.idx) fs.emplace_back(cur.idx);
      return;
    }
    if(rt->type==Type::Rake){
      assert(!left);
      dfs(dfs,rt->ch[0],d,false);
      dfs(dfs,rt->ch[1],d,false);
      return;
    }
    if(rt->type==Type::Compress){
      T mid=rt->ch[left?0:1]->dat.len;
      dfs(dfs,rt->ch[left?0:1],d,left);
      dfs(dfs,rt->ch[left?1:0],d+mid,left);
      dfs(dfs,rt->q,d+mid,false);
      return;
    }
    abort();
  };
  auto rt=G.expose(v);
  assert(rt->type==Type::Compress);
  dfs(dfs,rt->ch[0],T(0),false);
  dfs(dfs,rt->ch[1],T(0),true);
  dfs(dfs,rt->q,T(0),false);
  return fs;
}


#undef call_from_test

const int MAX = 2e5+100;
Vertex* vs[MAX];
int as[MAX],bs[MAX],ds[MAX];

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  const char newl = '\n';

  const size_t N = MAX;
  using Cluster = Farthest<long long>;
  TopTree<Vertex, Cluster, N> G;

  int n;
  cin>>n;

  for(int i=0;i<n;i++) vs[i]=G.create();

  for(int i=1;i<n;i++){
    cin>>as[i]>>bs[i]>>ds[i];
    as[i]--;bs[i]--;
    G.link(vs[as[i]],Cluster(ds[i],as[i],bs[i]),vs[bs[i]]);
  }

  auto cut=[&](int k)->void{
    G.cut(vs[as[k]],vs[bs[k]]);
  };
  auto link=[&](int k)->void{
    G.link(vs[as[k]],Cluster(ds[k],as[k],bs[k]),vs[bs[k]]);
  };

  int q;
  cin>>q;

  int cur=0;
  for(int i=0;i<q;i++){
    int t;
    cin>>t;

    if(t==1){
      int x;
      cin>>x;
      x--;
      cur=x;
    }
    if(t==2){
      int y;
      cin>>y;
      cut(y);
    }
    if(t==3){
      int z;
      cin>>z;
      link(z);
    }

    auto fs=get_all_farthests(G,vs[cur]);
    if(fs.empty()){
      cout<<1<<" "<<cur+1<<newl;
      continue;
    }

    sort(fs.begin(),fs.end());
    cout<<fs.size();
    for(int f:fs) cout<<" "<<f+1;
    cout<<newl;

    for(int f:fs) G.expose(vs[f]);
  }
  return 0;
}
accuracy: 1
time_ms: 1220
memory_kb: 118212
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll=long long;
#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

pi readpi(int off=0){
	int a,b;cin>>a>>b;
	return pi(a+off,b+off);
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
	#ifdef LOCAL
	cout.flush();
	#endif
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
ll mask(int i){
	return (ll(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
	static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
	#endif
	return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
void myshuffle(vc<t>&a){
	rep(i,si(a))swap(a[i],a[rand_int(0,i)]);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

vvc<int> readGraph(int n,int m){
	vvc<int> g(n);
	rep(i,m){
		int a,b;
		cin>>a>>b;
		//sc.read(a,b);
		a--;b--;
		g[a].pb(b);
		g[b].pb(a);
	}
	return g;
}

vvc<int> readTree(int n){
	return readGraph(n,n-1);
}

//merge で片方が inactive のときはもう片方をそのまま返す，
//といったときに，lazy の情報までコピーして渡さないようにする

//get の最後の引数は単位元と口では言いつつ・・・？
//たとえば min で最後の引数を 0 にしても 1 とかが返ってくることはある（一敗）

//VERIFY: yosupo
//KUPC2017I
//HDU 5306 Gorgeous Sequence
//findmin/max CF458E
template<class N>
struct segbeats{
	vc<N> x;
	int s;
	segbeats(){}
	template<class T>
	segbeats(const vc<T>& a){
		int n=a.size();
		s=1;
		while(s<n)s*=2;
		x.resize(s*2);
		rep(i,n)
			x[s+i]=N(a[i]);
		gnr(i,1,s)
			upd(i);
	}
	void push(int i){
		x[i].push(x[i*2],x[i*2+1]);
	}
	void upd(int i){
		x[i]=N::merge(x[i*2],x[i*2+1]);
	}
	template<class F,class... Args>
	void chr(int l,int r,int i,int b,int e,F f,Args&&... args){
		if(e<=l||r<=b)
			return;
		if(b<=l&&r<=e&&(x[i].*f)(forward<Args>(args)...))
			return;
		push(i);
		int m=(l+r)/2;
		chr(l,m,i*2,b,e,f,forward<Args>(args)...);
		chr(m,r,i*2+1,b,e,f,forward<Args>(args)...);
		upd(i);
	}
	template<class F,class... Args>
	void ch(int b,int e,F f,Args&&... args){
		assert(b<=e);
		chr(0,s,1,b,e,f,forward<Args>(args)...);
	}
	//use decltype((declval<N>().*F())()) for old-fashioned judges
	template<class F,class G,class H>
	auto getr(int l,int r,int i,int b,int e,F f,G g,H h){
		if(e<=l||r<=b)
			return h;
		if(b<=l&&r<=e)
			return (x[i].*f)();
		push(i);
		int m=(l+r)/2;
		return g(getr(l,m,i*2,b,e,f,g,h),getr(m,r,i*2+1,b,e,f,g,h));
	}
	template<class F,class G,class H>
	auto get(int b,int e,F f,G g,H h){
		assert(b<=e);
		return getr(0,s,1,b,e,f,g,h);
	}
	auto compositer(int l,int r,int i,int b,int e){
		if(e<=l||r<=b)assert(0);
		if(b<=l&&r<=e)
			return x[i];
		push(i);
		int m=(l+r)/2;
		if(e<=m)return compositer(l,m,i*2,b,e);
		if(m<=b)return compositer(m,r,i*2+1,b,e);
		return N::merge(compositer(l,m,i*2,b,e),compositer(m,r,i*2+1,b,e));
	}
	//work without identity node
	auto composite(int b,int e){
		assert(b<e);
		return compositer(0,s,1,b,e);
	}
	N getall(){return x[1];}
	//return minimum index
	template<class F,class...Args>
	pair<int,N> findminr(int i,int l,int r,int b,int e,F f,Args&&...args){
		if(e<=l||r<=b)return {e,N()};
		if(b<=l&&r<=e){
			if(!(x[i].*f)(forward<Args>(args)...))return {e,N()};
			if(r-l==1)return {l,x[i]};
		}
		push(i);
		int m=(l+r)/2;
		auto a=findminr(i*2,l,m,b,e,f,forward<Args>(args)...);
		if(a.a<e)return a;
		return findminr(i*2+1,m,r,b,e,f,forward<Args>(args)...);
	}
	template<class F,class...Args>
	pair<int,N> findmin(int b,int e,F f,Args&&...args){
		assert(b<=e);
		return findminr(1,0,s,b,e,f,forward<Args>(args)...);
	}
	//return maximum index
	template<class F,class...Args>
	pair<int,N> findmaxr(int i,int l,int r,int b,int e,F f,Args&&...args){
		if(e<=l||r<=b)return {b-1,N()};
		if(b<=l&&r<=e){
			if(!(x[i].*f)(forward<Args>(args)...))return {b-1,N()};
			if(r-l==1)return {l,x[i]};
		}
		push(i);
		int m=(l+r)/2;
		auto a=findmaxr(i*2+1,m,r,b,e,f,forward<Args>(args)...);
		if(a.a>=b)return a;
		return findmaxr(i*2,l,m,b,e,f,forward<Args>(args)...);
	}
	template<class F,class...Args>
	pair<int,N> findmax(int b,int e,F f,Args&&...args){
		assert(b<=e);
		return findmaxr(1,0,s,b,e,f,forward<Args>(args)...);
	}
	void enumerater(int l,int r,int i,int b,int e,vc<N>&dst){
		if(e<=l||r<=b)
			return;
		if(l+1==r){
			dst.pb(x[i]);
			return;
		}
		push(i);
		int m=(l+r)/2;
		enumerater(l,m,i*2,b,e,dst);
		enumerater(m,r,i*2+1,b,e,dst);
	}
	void enumerate(int b,int e,vc<N>&dst){
		assert(b<=e);
		return enumerater(0,s,1,b,e,dst);
	}
	template<class F,class...Args>
	void enumerate_by_findr(int l,int r,int i,int b,int e,vc<pair<int,N>>&dst,F f,Args&&...args){
		if(e<=l||r<=b||!(x[i].*f)(forward<Args>(args)...))
			return;
		if(l+1==r){
			dst.eb(l,x[i]);
			return;
		}
		push(i);
		int m=(l+r)/2;
		enumerate_by_findr(l,m,i*2,b,e,dst,f,forward<Args>(args)...);
		enumerate_by_findr(m,r,i*2+1,b,e,dst,f,forward<Args>(args)...);
	}
	template<class F,class...Args>
	void enumerate_by_find(int b,int e,vc<pair<int,N>>&dst,F f,Args&&...args){
		assert(b<=e);
		enumerate_by_findr(0,s,1,b,e,dst,f,forward<Args>(args)...);
	}
	void prepare(int i){
		if(i/=2){
			prepare(i);
			push(i);
		}
	}
	//point_update と lazy を組み合わせたらどうなるかは，わからない・・・
	void point_update(int i,N w){
		i+=s;
		prepare(i);
		x[i]=w;
		while(i/=2)
			upd(i);
	}
};

//N::push
//pushしたあとはclearする
//N::merge

struct N{
	int a,c,la,lc;
	N(int v=-inf):a(v),c(v==-inf?inf:0),la(0),lc(0){}
	bool add_a(int v){
		a+=v;
		la+=v;
		return true;
	}
	bool add_c(int v){
		c+=v;
		lc+=v;
		return true;
	}
	void push_sub(N&x){
		x.add_a(la);
		x.add_c(lc);
	}
	void push(N&x,N&y){
		push_sub(x);
		push_sub(y);
		la=0;
		lc=0;
	}
	void upd_sub(const N&x){
		if(c==x.c)chmax(a,x.a);
	}
	static N merge(const N&x,const N&y){
		N res;
		res.c=min(x.c,y.c);
		res.upd_sub(x);
		res.upd_sub(y);
		return res;
	}
	bool find(int v){
		return c==0&&v==a;
	}
};

template<class ES>
struct treedfs{
	const vc<ES>&g;
	const int n;
	int cnt;
	vi par,dep,in,out;
	void dfs(int v,int p,int d){
		par[v]=p;
		dep[v]=d;
		in[v]=cnt++;
		for(auto e:g[v])if(e.a!=p)
			dfs(e.a,v,d+e.b);
		out[v]=cnt;
	}
	treedfs(const vc<ES>&gg,int r):g(gg),n(si(g)),cnt(0),par(n),dep(n),in(n),out(n){
		dfs(r,-1,0);
	}
};

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);
	
	int n;cin>>n;
	vc<map<int,int>> t(n);
	vc<pi> es;
	rep(i,n-1){
		int a,b;cin>>a>>b;
		a--;b--;
		int d;cin>>d;
		t[a][b]=d;
		t[b][a]=d;
		es.eb(a,b);
	}
	
	treedfs<map<int,int>> z(t,0);
	vi ls(n);
	rep(i,n)ls[z.in[i]]=z.dep[i];
	vi ni(n);
	rep(i,n)ni[z.in[i]]=i;
	segbeats<N> seg(ls);
	
	auto answer=[&](){
		int tar=seg.getall().a;
		vc<pair<int,N>> buf;
		seg.enumerate_by_find(0,n,buf,&N::find,tar);
		vi ans(si(buf));
		rep(i,si(buf))ans[i]=ni[buf[i].a]+1;
		sort(all(ans));
		print(si(ans),2);
		print(ans);
	};
	
	auto add=[&](int v,int w){
		seg.ch(0,z.in[v],&N::add_a,-w);
		seg.ch(z.in[v],z.out[v],&N::add_a,w);
		seg.ch(z.out[v],n,&N::add_a,-w);
	};
	
	auto addc_out=[&](int v,int w){
		seg.ch(0,z.in[v],&N::add_c,w);
		seg.ch(z.out[v],n,&N::add_c,w);
	};
	
	auto addc_in=[&](int v,int w){
		seg.ch(z.in[v],z.out[v],&N::add_c,w);
	};
	
	int cur=0;
	int q;cin>>q;
	rep(_,q){
		int tp;cin>>tp;
		if(tp==1){
			int x;cin>>x;x--;
			int d=t[cur][x];
			if(x==z.par[cur]){
				add(cur,d);
			}else{
				add(x,-d);
			}
			cur=x;
		}else if(tp==2){
			int a,b;tie(a,b)=es[read()-1];
			if(z.par[a]!=b)swap(a,b);
			if(inc(z.in[a],z.in[cur],z.out[a]-1)){
				addc_out(a,1);
			}else{
				addc_in(a,1);
			}
		}else{
			int a,b;tie(a,b)=es[read()-1];
			if(z.par[a]!=b)swap(a,b);
			if(inc(z.in[a],z.in[cur],z.out[a]-1)){
				addc_out(a,-1);
			}else{
				addc_in(a,-1);
			}
		}
		answer();
	}
}
accuracy: 1
time_ms: 440
memory_kb: 73000
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}()); 
const ll mod=998244353;
int rnd(int x) { return mrand() % x;}
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
// head

const int N=201000;

int n,u,v,w,q,ty,x;
vector<PII> e[N];
ll dis[N];
int l[N],r[N],tot,id[N],par[N],pare[N],rt;
PII E[N];

void dfs(int u,int f) {
	l[u]=++tot;
	id[tot]=u;
	//printf("%d %d\n",u,f);
	for (auto p:e[u]) {
		if (p.fi==f) continue;
		dis[p.fi]=dis[u]+p.se;
		par[p.fi]=u;
		pare[p.fi]=p.se;
		dfs(p.fi,u);
	}
	r[u]=tot;
}

struct node {
	pair<ll,int> dis;
	ll tag;
}nd[4*N];
void upd(int p) {
	nd[p].dis=max(nd[p+p].dis,nd[p+p+1].dis);
}
void setf(int p,ll v) {
	nd[p].tag+=v;
	nd[p].dis.fi+=v;
}
void build(int p,int l,int r) {
	if (l==r) {
		nd[p].dis=mp(dis[id[l]],id[l]);
	} else {
		int md=(l+r)>>1;
		build(p+p,l,md);
		build(p+p+1,md+1,r);
		upd(p);
	}
}
void push(int p) {
	if (nd[p].tag) {
		setf(p+p,nd[p].tag);
		setf(p+p+1,nd[p].tag);
		nd[p].tag=0;
	}
}
pair<ll,int> query(int p,int l,int r,int tl,int tr) {
	if (tl==l&&tr==r) return nd[p].dis;
	else {
		push(p);
		int md=(l+r)>>1;
		if (tr<=md) return query(p+p,l,md,tl,tr);
		else if (tl>md) return query(p+p+1,md+1,r,tl,tr);
		else return min(query(p+p,l,md,tl,md),query(p+p+1,md+1,r,md+1,tr));
	}
}
void modify(int p,int l,int r,int tl,int tr,ll v) {
	//if (p==1) printf("Modify %d %d %lld\n",tl,tr,v);
	if (tl>tr) return;
	if (tl==l&&tr==r) return setf(p,v);
	else {
		push(p);
		int md=(l+r)>>1;
		if (tr<=md) modify(p+p,l,md,tl,tr,v);
		else if (tl>md) modify(p+p+1,md+1,r,tl,tr,v);
		else modify(p+p,l,md,tl,md,v),modify(p+p+1,md+1,r,md+1,tr,v);
		upd(p);
	}
}

void print() {
	ll x=nd[1].dis.fi;
	VI cc;
	//printf("%lld %d\n",nd[1].dis.fi,nd[1].dis.se);
	while (nd[1].dis.fi==x) {
		int u=nd[1].dis.se;
		cc.pb(u);
		modify(1,1,n,l[u],l[u],-(1ll<<62));
	}
	sort(all(cc));
	printf("%d",SZ(cc));
	for (auto x:cc) {
		printf(" %d",x);
		modify(1,1,n,l[x],l[x],(1ll<<62));	
	}
	puts("");
}

const ll inf=1ll<<42;

int main() {
	scanf("%d",&n);
	rep(i,1,n) {
		scanf("%d%d%d",&u,&v,&w);
		e[u].pb({v,w});
		e[v].pb({u,w});
		E[i]={u,v};
	}
	dfs(1,0);
	build(1,1,n);
	//puts("gg");
	rt=1;
	scanf("%d",&q);
	rep(i,0,q) {
		scanf("%d%d",&ty,&x);
		if (ty==1) {
			// move
			if (x==par[rt]) {
				modify(1,1,n,l[rt],r[rt],2*pare[rt]);
			} else {
				modify(1,1,n,l[x],r[x],-2*pare[x]);
			}
			rt=x;
		} else {
			u=E[x].fi, v=E[x].se;
			if (v==par[u]) swap(u,v); // u=par[v]
			if (l[v]<=l[rt]&&r[rt]<=r[v]) {
				modify(1,1,n,l[v],r[v],(ty==2)?inf:-inf);
			} else {
				modify(1,1,n,l[v],r[v],(ty==2)?-inf:inf);
			}
		}
		print();
	}
}
accuracy: 1
time_ms: 310
memory_kb: 49556
final_rank: 2

code_snippet: #include <vector>
#include <iostream>
#include <string>
#include <cassert>
using i64 = long long;

namespace toptree {
  struct cluster {
    struct dist {
      i64 d; int to;
      dist(): d(0), to(-1) {}
      dist(i64 d, i64 to): d(d), to(to) {}
      bool operator<(const dist& r) const { return d < r.d; }
      dist operator+(const i64& r) const { return dist(d + r, to); }
    };
    dist max_dist_left;
    dist max_dist_right;
    i64 length;

    cluster(i64 l = 0, int a = -1, int b = -1): max_dist_left(l, b), max_dist_right(l, a), length(l) {}
    cluster(dist b, dist c, i64 d): max_dist_left(b), max_dist_right(c), length(d) {}
    static cluster identity() {
      return cluster(0);
    }
    static cluster compress(const cluster& a, const cluster& b) {
      return cluster(
          std::max(a.max_dist_left, b.max_dist_left + a.length),
          std::max(b.max_dist_right, a.max_dist_right + b.length),
          a.length + b.length
          );
    }
    static cluster rake(const cluster& a, const cluster& b) {
      return cluster(
          std::max(a.max_dist_left, b.max_dist_right + a.length),
          std::max(a.max_dist_right, b.max_dist_right),
          a.length
          );
    }
    static cluster reverse(const cluster& c) {
      cluster res = c;
      std::swap(res.max_dist_left, res.max_dist_right);
      return res;
    }
  };

  struct vertex;
  struct node;

  using size_type = std::size_t;
  using node_index = std::uint_least32_t;
  using vertex_index = std::uint_least32_t;

  extern struct vertex v[404040];
  extern size_type vi;
  extern struct node n[2020202];
  extern size_type ni;
  extern node_index guard;

  void link(node_index a, node_index b, cluster weight);

  struct vertex {
    node_index hn;
  };

  vertex_index new_vertex() {
    v[vi++] = { 0 };
    v[vi++] = { 0 };
    link(vi - 2, vi - 1, cluster::identity());
    return vi - 2;
  }


  enum class type { Compress, Rake, Edge };


  struct node {
    node_index i;
    node_index c[4];
    bool rev;
    cluster f;
    vertex_index v[2];
    type ty;

    inline node& operator[](size_type d) { return n[c[d]]; }
    inline vertex& operator()(size_type d) { return toptree::v[this->v[d]]; }
  };

  inline node_index new_node(type ty) {
    node_index i = ni++;
    n[i].i = i;
    n[i].ty = ty;
    return i;
  }

  void reverse(node_index i) {
    std::swap(n[i].v[0], n[i].v[1]);
    n[i].f = cluster::reverse(n[i].f);
    n[i].rev ^= true;
  }

  void push(node_index i) {
    if(n[i].ty != type::Edge && n[i].rev) {
      std::swap(n[i].c[0], n[i].c[1]);
      reverse(n[i].c[0]);
      reverse(n[i].c[1]);
      n[i].rev = false;
    }
  }

  void fix(node_index i) {
    push(i);
    if(n[i].ty == type::Compress) {
      n[i].v[0] = n[i][0].v[0];
      n[i].v[1] = n[i][1].v[1];
      cluster l = n[i][0].f;
      if(n[i].c[2])
        l = cluster::rake(l, n[i][2].f);
      n[i].f = cluster::compress(l, n[i][1].f);
    }
    if(n[i].ty == type::Rake) {
      n[i].v[0] = n[i][0].v[0];
      n[i].v[1] = n[i][0].v[1];
      n[i].f = cluster::rake(n[i][0].f, n[i][1].f);
    }

    if(n[i].ty == type::Compress)
      n[i][1](0).hn = i;
    if(n[i].ty != type::Rake) {
      if(!n[i].c[3])
        n[i](0).hn = n[i](1).hn = i;
      else if(n[i][3].ty == type::Rake || n[i][3].c[2] == n[i].i)
        n[i](0).hn = i;
    }
  }


  int child_dir(node_index i) {
    if(n[i].c[3]) {
      if(n[i][3].c[0] == i) { return 0; }
      else if(n[i][3].c[1] == i) { return 1; }
      else { return 2; }
    }
    return 3;
  }

  void rotate(node_index x, size_type dir) {
    node_index p = n[x].c[3];
    int x_dir = child_dir(x);
    node_index y = n[x].c[dir ^ 1];
    n[n[y][dir].c[3] = x].c[dir ^ 1] = n[y].c[dir];
    n[n[x].c[3] = y].c[dir] = x;
    n[y].c[3] = p;
    if(x_dir < 3) n[p].c[x_dir] = y;
    fix(x);
    fix(y);
    if(p && p != guard) fix(p);
  }

  void splay(node_index i) {
    push(i);
    int i_dir;
    int j_dir;
    while(child_dir(i) < 2 && n[i].c[3] != guard && n[i].ty == n[i][3].ty) {
      node_index j = n[i].c[3];
      if(child_dir(j) < 2 && n[j].c[3] != guard && n[j].ty == n[j][3].ty) {
        node_index k = n[j].c[3];
        if(n[k].c[3]) push(n[k].c[3]);
        push(k), push(j), push(i);
        i_dir = child_dir(i);
        j_dir = child_dir(j);
        if(i_dir == j_dir) rotate(k, j_dir ^ 1), rotate(j, i_dir ^ 1);
        else rotate(j, i_dir ^ 1), rotate(k, j_dir ^ 1);
      }
      else {
        if(n[j].c[3]) push(n[j].c[3]);
        push(j), push(i);
        rotate(j, child_dir(i) ^ 1);
      }
    }
  }

  node_index expose_raw(node_index i) {
    while(true) {
      if(n[i].ty == type::Compress) splay(i);
      node_index p = n[i].c[3];
      if(!p) break;
      else if(n[p].ty == type::Rake) {
        splay(p);
        p = n[p].c[3];
      }
      else if(p == toptree::guard && child_dir(i) < 2) break;
      splay(p);

      int dir = child_dir(p);
      dir = (dir >= 2 || n[p][3].ty == type::Rake) ? 0 : dir;
      if(dir == 1) {
        reverse(n[p].c[dir]);
        reverse(i);
      }

      int i_dir = child_dir(i);
      int x = n[i].c[3];
      int m = n[p].c[dir];

      n[n[m].c[3] = x].c[i_dir] = m;
      n[n[i].c[3] = p].c[dir] = i;
      if(n[x].ty == type::Rake) {
        fix(m); fix(x); fix(i); fix(p);
        splay(x);
      }
      else {
        fix(m); fix(i); fix(p);
      }
      if(n[i].ty == type::Edge) {
        i = p;
      }
    }
    return i;
  }

  node_index expose(vertex_index i) {
    return expose_raw(v[i].hn);
  }

  void soft_expose(vertex_index a, vertex_index b) {
    node_index r = expose(a);
    if(v[a].hn == v[b].hn) {
      if(n[r].c[1] == a || n[r].c[0] == b) reverse(r), push(r);
      return;
    }
    guard = r;
    node_index s = expose(b);
    guard = ~0;
    fix(r);
    if(child_dir(s) == 0) reverse(r), push(r), push(s);
  }


  void link(vertex_index a, vertex_index b, cluster weight) {
    node_index e = new_node(type::Edge);
    n[e].v[0] = a; n[e].v[1] = b; n[e].f = weight;
    if(!v[a].hn && !v[b].hn) { fix(e); return; }
    node_index na = v[a].hn;
    node_index nb = v[b].hn;
    node_index left;
    for(int dir = 0; dir < 2; dir++) {
      if(!nb) left = e;
      else {
        nb = expose_raw(nb);
        if(n[nb].v[dir ^ 1] == b) {
          reverse(nb);
          push(nb);
        }
        if(n[nb].v[dir] == b) {
          left = new_node(type::Compress);
          n[left].c[dir] = e; n[left].c[dir ^ 1] = nb;
          n[e].c[3] = n[nb].c[3] = left;
          fix(e); fix(nb); fix(left);
        }
        else {
          node_index ch = n[nb].c[dir];
          if(dir) reverse(ch);
          n[n[e].c[3] = nb].c[dir] = e;
          node_index beta = n[nb].c[2];
          node_index rake;
          if(beta) {
            rake = new_node(type::Rake);
            n[rake].c[0] = beta; n[rake].c[1] = ch;
            n[beta].c[3] = n[ch].c[3] = rake;
            fix(beta); fix(ch);
          }
          else rake = ch;
          n[n[rake].c[3] = nb].c[2] = rake;
          fix(rake); fix(e); fix(left = nb);
        }
      }
      e = left;
      nb = na;
      b = a;
    }
  }

  cluster path_query(vertex_index a, vertex_index b) {
    soft_expose(a, b);
    node_index r = v[a].hn;
    if(n[r].v[0] == a && n[r].v[1] == b) return n[r].f;
    if(n[r].v[0] == a) return n[r][0].f;
    if(n[r].v[1] == b) return n[r][1].f;
    push(n[r].c[1]);
    return n[r][1][0].f;
  }

  void bring(node_index r, int dir) {
    node_index i = n[r].c[2];
    if(!i) {
      i = n[r].c[dir ^ 1];
      n[i].c[3] = 0;
      fix(i);
    }
    else if(n[i].ty == type::Rake) {
      while(push(i), n[i][1].ty == type::Rake) i = n[i].c[1];
      guard = r;
      splay(i);
      guard = ~0;
      n[n[i][0].c[3] = r].c[2] = n[i].c[0];
      if(dir) reverse(n[i].c[1]);
      n[n[i][1].c[3] = r].c[dir] = n[i].c[1];
      fix(n[r].c[2]); fix(n[r].c[dir]); fix(r);
    }
    else {
      if(dir) reverse(i);
      n[n[i].c[3] = r].c[dir] = i;
      n[r].c[2] = 0;
      fix(n[r].c[dir]); fix(r);
    }
  }

  void cut(node_index a, node_index b) {
    soft_expose(a, b);
    node_index r = v[a].hn;
    push(r);
    node_index s = n[r].c[1];
    push(s);
    n[s].c[3] = 0;
    n[r].c[1] = 0;
    bring(r, 1);
    bring(s, 0);
  }

  cluster::dist mid(node_index a) {
    node_index i = expose(a);
    push(i);
    return std::max(n[i][0].f.max_dist_right, n[i][1].f.max_dist_left);
  }
}

toptree::vertex toptree::v[404040];
toptree::size_type toptree::vi = 1;
toptree::node toptree::n[2020202];
toptree::size_type toptree::ni = 1;
toptree::node_index toptree::guard = ~0;

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
#define all(x) x.begin(),x.end()

template<class T>
static inline std::vector<T> ndvec(size_t&& n, T val) noexcept {
  return std::vector<T>(n, std::forward<T>(val));
}

template<class... Tail>
static inline auto ndvec(size_t&& n, Tail&&... tail) noexcept {
  return std::vector<decltype(ndvec(std::forward<Tail>(tail)...))>(n, ndvec(std::forward<Tail>(tail)...));
}

template<class T, class Cond>
struct chain {
  Cond cond; chain(Cond cond) : cond(cond) {}
  bool operator()(T& a, const T& b) const {
    if(cond(a, b)) { a = b; return true; }
    return false;
  }
};
#include <iostream>
#include <vector>
#include <tuple>

using namespace std;

#include <cstdio>

namespace niu {
  char cur;
  struct FIN {
    static inline bool is_blank(char c) { return c <= ' '; }
    inline char next() { return cur = getc_unlocked(stdin); }
    inline char peek() { return cur; }
    inline void skip() { while(is_blank(next())){} }
#define intin(inttype)  \
    FIN& operator>>(inttype& n) { \
      bool sign = 0; \
      n = 0; \
      skip(); \
      while(!is_blank(peek())) { \
        if(peek() == '-') sign = 1; \
        else n = (n << 1) + (n << 3) + (peek() & 0b1111); \
        next(); \
      } \
      if(sign) n = -n; \
      return *this; \
    }
intin(int)
intin(long long)
  } fin;

  char tmp[128];
  struct FOUT {
    static inline bool is_blank(char c) { return c <= ' '; }
    inline void push(char c) { putc_unlocked(c, stdout); }
    FOUT& operator<<(char c) { push(c); return *this; }
    FOUT& operator<<(const char* s) { while(*s) push(*s++); return *this; }
#define intout(inttype) \
    FOUT& operator<<(inttype n) { \
      if(n) { \
        char* p = tmp + 127; bool neg = 0; \
        if(n < 0) neg = 1, n = -n; \
        while(n) *--p = (n % 10) | 0b00110000, n /= 10; \
        if(neg) *--p = '-'; \
        return (*this) << p; \
      } \
      else { \
        push('0'); \
        return *this; \
      } \
    }
intout(int)
intout(long long)
  } fout;
}

template<class T, class Cond>
chain<T, Cond> make_chain(Cond cond) { return chain<T, Cond>(cond); }
int main() {
  using niu::fin;
  using niu::fout;
  i64 N, Q;
  fin >> N;
  vector<int> vs(N);
  vector<i64> leaf(N);
  for(int i = 0;i < N;i++) {
    vs[i] = toptree::new_vertex();
  }
  vector<int> A(N - 1), B(N - 1), D(N - 1);
  for(int i = 0;i + 1 < N;i++) {
    fin >> A[i] >> B[i] >> D[i];
    A[i]--;
    B[i]--;
    toptree::link(vs[A[i]], vs[B[i]], toptree::cluster(D[i], A[i], B[i]));
    leaf[A[i]] += i;
    leaf[B[i]] += i;
  }
  fin >> Q;
  int now = 0;
  vector<int> ans(N);
  for(int i = 0;i < Q;i++) {
    int c, x;
    fin >> c >> x;
    x--;
    if(c == 1) {
      now = x;
    }
    else if(c == 2) {
      toptree::cut(vs[A[x]], vs[B[x]]);
      leaf[A[x]] -= x;
      leaf[B[x]] -= x;
    }
    else {
      toptree::link(vs[A[x]], vs[B[x]], toptree::cluster(D[x], A[x], B[x]));
      leaf[A[x]] += x;
      leaf[B[x]] += x;
    }
    i64 MAX = toptree::mid(vs[now]).d;
    if(MAX == 0) {
      fout << 1 << " " << now + 1 << '\n';
      continue;
    }
    int ai = 0;
    while(true) {
      auto res = toptree::mid(vs[now]);
      if(res.d < MAX) break;
      ans[ai++] = res.to;
      int idx = leaf[res.to];
      toptree::cut(vs[A[idx]], vs[B[idx]]);
    }

    sort(begin(ans), begin(ans) + ai);
    fout << ai;
    rep(j,0,ai) fout << ' ' << ans[j] + 1;
    fout << '\n';
    rep(j,0,ai)  {
      int idx = leaf[ans[j]];
      toptree::link(vs[A[idx]], vs[B[idx]], toptree::cluster(D[idx], A[idx], B[idx]));
    }
  }
}
accuracy: 0.06666666666666667
time_ms: 510
memory_kb: 167788
final_rank: 13

code_snippet: #include <vector>
#include <iostream>
#include <string>
#include <cassert>
using i64 = long long;

struct cluster {
  struct dist {
    i64 d; int to;
    dist(): d(0), to(-1) {}
    dist(i64 d, i64 to): d(d), to(to) {}
    bool operator<(const dist& r) const { return d < r.d; }
    dist operator+(const i64& r) const { return dist(d + r, to); }
  };
  dist ans;
  dist max_dist_left;
  dist max_dist_right;
  i64 length;
 
  using V = std::size_t;
  cluster(i64 l = 0, int a = -1, int b = -1): ans(), max_dist_left(l, b), max_dist_right(l, a), length(l) {}
  cluster(dist a, dist b, dist c, i64 d): ans(a), max_dist_left(b), max_dist_right(c), length(d) {}
  static cluster identity() {
    return cluster(0);
  }
    static V v_identity() {
      return 0;
    }
  static cluster compress(const cluster& a, const cluster& b, V _x, V _y, V _z) {
    return cluster(
        std::max(a.max_dist_right, b.max_dist_left),
        std::max(a.max_dist_left, b.max_dist_left + a.length),
        std::max(b.max_dist_right, a.max_dist_right + b.length),
        a.length + b.length
        );
  }
  static cluster rake(const cluster& a, const cluster& b, V _x, V _y, V _z) {
    return cluster(
        dist(),
        std::max(a.max_dist_left, b.max_dist_right + a.length),
        std::max(a.max_dist_right, b.max_dist_right),
        a.length
        );
  }
  static cluster reverse(const cluster& c) {
    cluster res = c;
    std::swap(res.max_dist_left, res.max_dist_right);
    return res;
  }
 
  static std::size_t select(const cluster& a, const cluster& b, V av, V bv, V cv) {
    return 0;
  }
};

#include <utility>
#include <array>
#include <cassert>

using i64 = long long;

class vertex;

class node;
int parent_dir(node*);
node* link(vertex, vertex, cluster);
void test_comp_set(node* n);

class vertex_raw {
  cluster::V val;
  node* hand;

public:

  vertex_raw(cluster::V val): val(val), hand(nullptr) {}

  node* handle() const { return this->hand; }
  void set_handle(node* hand) { this->hand = hand; }
  const cluster::V& value() const { return this->val; }
  void set_value(cluster::V val) {
    this->val = val;
  }
};

class vertex {
  vertex_raw* ver;

private:


public:

  static vertex dangling() { return vertex(); } 

  vertex(): ver(nullptr) {}
  vertex(cluster::V val): ver( new vertex_raw(val)) {
    vertex dummy;
    dummy.ver = new vertex_raw(cluster::V());
    link(*this, dummy, cluster::identity());
  }

  bool operator==(const vertex& other) { return this->ver == other.ver; }
  
  inline node* handle() const { return this->ver->handle(); }
  inline void set_handle(node* hand) { this->ver->set_handle(hand); }
  inline const cluster::V& value() const { return this->ver->value(); }
  inline void set_value(cluster::V val) { this->ver->set_value(val); }
};

enum class Type { Compress, Rake, Edge, None };

static std::size_t ni = 0;
extern node ns[1515151];

class node {
  node* ch[2];
  node* par;
  node* ra;
  node* me;
  bool rev;
  cluster fo;
  vertex v[2];
  Type ty;



public:

  node(): par(nullptr), ra(nullptr), me(nullptr), rev(false),
    fo(cluster::identity()), ty(Type::None) {} 



  static node* new_edge(vertex v, vertex u, cluster val) {
    //node* n = new node();
    node* n = ns + (ni++);
    n->v[0] = v;
    n->v[1] = u;
    n->fo = val;
    n->me = n;
    n->ty = Type::Edge;

    n->fix();

    return n;
  }

  static node* new_compress(node* left, node* right) {
    //node* n = new node();
    node* n = ns + (ni++);
    n->ch[0] = left;
    n->ch[1] = right;
    n->me = n;
    n->ty = Type::Compress;
    n->fix();
    return n;
  }

  static node* new_rake(node* left, node* right) {
    //node * n = new node();
    node* n = ns + (ni++);
    n->ch[0] = left;
    n->ch[1] = right;
    n->me = n;
    n->ty = Type::Rake;
    n->fix();
    return n;
  }

  inline void fix() {
    if(this->ty == Type::Edge) {
      if(!this->parent()) {
        this->endpoint(0).set_handle(this->me);
        this->endpoint(1).set_handle(this->me);
      }
      else if(this->parent()->ty == Type::Compress) {
        if(parent_dir(this->me) == -1) {
          this->endpoint(0).set_handle(this->me);
        }
      }
      else if(this->parent()->ty == Type::Rake) {
        this->endpoint(0).set_handle(this->me);
      }
    }
    else if(this->ty == Type::Compress) {
      this->push();
      this->v[0] = this->child(0)->endpoint(0);
      this->v[1] = this->child(1)->endpoint(1);
      assert(this->child(0)->endpoint(1) == this->child(1)->endpoint(0));

      cluster left = this->child(0)->fold();
      node* l = this->child(0);
      if(this->rake()) {
        node* r = this->rake();
        left = cluster::rake(l->fold(), r->fold(), l->endpoint(0).value(), r->endpoint(0).value(), l->endpoint(1).value());
      }
      node* r = this->child(1);
      this->fo= cluster::compress(left, r->fold(),
          l->endpoint(0).value(), r->endpoint(1).value(), l->endpoint(1).value());
      
      this->child(0)->endpoint(1).set_handle(this->me);

      if(!this->parent()) {
        this->endpoint(0).set_handle(this->me);
        this->endpoint(1).set_handle(this->me);
      }
      else if(this->parent()->ty == Type::Compress) {
        if(parent_dir(this->me) == -1) {
          this->endpoint(0).set_handle(this->me);
        }
      }
      else if(this->parent()->ty == Type::Rake) {
        this->endpoint(0).set_handle(this->me);
      }

    }
    else if(this->ty == Type::Rake) {
      this->push();
      this->v[0] = this->child(0)->endpoint(0);
      this->v[1] = this->child(0)->endpoint(1);
      this->fo = cluster::rake(this->child(0)->fold(), this->child(1)->fold(),
          this->child(0)->endpoint(0).value(), this->child(1)->endpoint(0).value(), this->child(0)->endpoint(1).value());
    }
    else { assert(false); }
  }

  inline void push() {
    if(this->ty == Type::Compress) {
      if(this->rev) {
        std::swap(this->ch[0], this->ch[1]);
        this->child(0)->reverse();
        this->child(1)->reverse();
        this->rev = false;
      }
    }
  }

  inline void reverse() {
    if(this->ty == Type::Edge) {
      std::swap(this->v[0], this->v[1]);
      this->fo = cluster::reverse(this->fold());
    }
    else if(this->ty == Type::Compress) {
      std::swap(this->v[0], this->v[1]);
      this->fo = cluster::reverse(this->fold());
      this->rev ^= true;
    }
    else if(this->ty == Type::Rake) {
    }
    else { assert(false); }
  }

  inline node* parent() const { return this->par; }
  inline void set_parent(node* par) { this->par = par; }
  inline node* rake() const { return this->ra; }
  inline void set_rake(node* rake) { this->ra = rake; }
  inline node* child(std::size_t dir) const { return this->ch[dir]; }
  inline void set_child(node* ch, std::size_t dir) { this->ch[dir] = ch; }
  inline vertex endpoint(std::size_t dir) { return this->v[dir]; }
  inline Type type() const { return this->ty; }

  cluster fold() const { return this->fo; }

  bool guard;
};

int parent_dir(node* child) {
  node* par = child->parent();
  if(par) {
    if(par->guard) { return -1; }
    else if(par->child(0) == child) { return 0; }
    else if(par->child(1) == child) { return 1; }
    else { return -1; }
  }
  else { return -1; }
}

int parent_dir_guard(node* child) {
  node* par = child->parent();
  if(par) {
    if(par->child(0) == child) { return 0; }
    else if(par->child(1) == child) { return 1; }
    else { return -1; }
  }
  else { return -1; }
}

void rotate(node* t, node* x, std::size_t dir) {
  node* y = x->parent();
  int par = parent_dir_guard(x);
  t->child(dir)->push();
  x->set_child(t->child(dir), dir ^ 1);
  t->child(dir)->set_parent(x);
  t->set_child(x, dir);
  x->set_parent(t);
  t->set_parent(y);
  if(par != -1) {
    y->set_child(t, par);
  }
  else if(y && y->type() == Type::Compress) {
    y->set_rake(t);
  }
  x->fix();
  t->fix();
  if(y && !y->guard) { y->fix(); }
}

void splay(node* t) {
  assert(t->type() != Type::Edge);
  t->push();

  while(parent_dir(t) != -1) {
    node* q = t->parent();
    if(q->type() != t->type()) break;
    if(parent_dir(q) != -1 && q->parent() && q->parent()->type() == q->type()) {
      node* r = q->parent();
      if(r->parent()) r->parent()->push();
      r->push();
      q->push();
      t->push();
      int qt_dir = parent_dir(t);
      int rq_dir = parent_dir(q);
      if(rq_dir == qt_dir) {
        rotate(q, r, rq_dir ^ 1);
        rotate(t, q, qt_dir ^ 1);
      }
      else {
        rotate(t, q, qt_dir ^ 1);
        rotate(t, r, rq_dir ^ 1);
      }
    }
    else {
      if(q->parent()) q->parent()->push();
      q->push();
      t->push();
      int qt_dir = parent_dir(t);
      rotate(t, q, qt_dir ^ 1);
    }
  }
}

node* expose_raw(node* t) {
  while(true) {
    assert(t->type() != Type::Rake);
    if(t->type() == Type::Compress) {
      splay(t);
    }
    node* n = nullptr;
    {
      node* par = t->parent();
      if(!par) { break; }
      else if(par->type() == Type::Rake) {
        par->push();
        splay(par);
        n = par->parent();
      }
      else if(par->type() == Type::Compress) {
        par->push();
        if(par->guard && parent_dir_guard(t) != -1) { break; }
        n = par;
      }
      else { assert(false); }
    }

    splay(n);

    
    int dir = parent_dir_guard(n);
    if(dir == -1 || n->parent()->type() == Type::Rake) dir = 0;
    if(dir == 1) {
      n->child(dir)->reverse();
      n->child(dir)->push();
      t->reverse();
      t->push();
    }
    int n_dir = parent_dir(t);
    if(n_dir != -1) {
      node* nch = n->child(dir);
      nch->push();
      node* rake = t->parent();
      rake->push();

      rake->set_child(nch, n_dir);
      nch->set_parent(rake);
      n->set_child(t, dir);
      t->set_parent(n);
      nch->fix();
      rake->fix();
      t->fix();
      n->fix();
      splay(rake);
    }
    else {
      node* nch = n->child(dir);
      nch->push();
      n->set_rake(nch);
      nch->set_parent(n);
      n->set_child(t, dir);
      t->set_parent(n);

      nch->fix();
      t->fix();
      n->fix();
    }
    if(t->type() == Type::Edge) {
      t = n;
    }
  }
  
  return t;
}

node* expose(vertex ver) {
  return expose_raw(ver.handle());
}

void soft_expose(vertex v, vertex u) {
  node* root = expose(v);
  if(v.handle() == u.handle()) {
    if(root->endpoint(1) == v || root->endpoint(0) == u) {
      root->reverse();
      root->push();
    }
    return;
  }
  root->guard = true;
  node* soot = expose(u);
  root->guard = false;
  root->fix();
  if(parent_dir(soot) == 0) {
    root->reverse();
    root->push();
  }
}

node* link(vertex v, vertex u, cluster weight) {
  if(!v.handle() && !u.handle()) {
    return node::new_edge(v, u, weight);
  }
  else {
    node* nnu = u.handle();
    node* nnv = v.handle();
    node* e = node::new_edge(v, u, weight);
    node* left = nullptr;

    if(!nnu) { left = e; }
    else {
      node* uu = expose_raw(nnu);
      uu->push();
      if(uu->endpoint(1) == u) {
        uu->reverse();
        uu->push();
      }
      if(uu->endpoint(0) == u) {
        node* nu = node::new_compress(e, uu);
        e->set_parent(nu);
        e->fix();
        uu->set_parent(nu);
        uu->fix();
        nu->fix();

        left = nu;
      }
      else {
        node* nu = uu;
        node* left_ch = nu->child(0);
        left_ch->push();

        nu->set_child(e, 0);
        e->set_parent(nu);
        e->fix();
        
        node* beta = nu->rake();
        node* rake = nullptr;
        if(beta) {
          beta->push();
          rake = node::new_rake(beta, left_ch);
          beta->set_parent(rake);
          left_ch->set_parent(rake);
          beta->fix();
          left_ch->fix();
        }
        else {
          rake = left_ch;
        }
        nu->set_rake(rake);
        rake->set_parent(nu);
        rake->fix();
        nu->fix();

        left = nu;
      }
    }

    if(!nnv) {}
    else {
      node* vv =expose_raw(nnv);
      vv->push();
      if(vv->endpoint(0) == v) {
        vv->reverse();
        vv->push();
      }
      if(vv->endpoint(1) == v) {
        node* top = node::new_compress(vv, left);
        vv->set_parent(top);
        left->set_parent(top);
        vv->fix();
        left->fix();
        top->fix();
      }
      else {
        node* nv = vv;
        node* right_ch = nv->child(1);
        right_ch->reverse();
        right_ch->push();

        nv->set_child(left, 1);
        left->set_parent(nv);
        left->fix();

        node* alpha = nv->rake();
        node* rake = nullptr;
        if(alpha) {
          alpha->push();
          rake = node::new_rake(alpha, right_ch);
          alpha->set_parent(rake);
          alpha->fix();
          right_ch->set_parent(rake);
          right_ch->fix();
        }
        else {
          rake = right_ch;
        }
        nv->set_rake(rake);
        rake->set_parent(nv);
        rake->fix();
        nv->fix();
      }
    }

    return e;
  }
}

void bring(node* root) {
  node* rake = root->rake();

  if(!rake) {
    node* left = root->child(0);
    //delete root, root = nullptr;
    left->set_parent(nullptr);
    left->fix();
  }
  else if(rake->type() == Type::Compress || rake->type() == Type::Edge) {
    rake->push();
    node* new_right = rake;
    new_right->reverse();
    new_right->push();

    root->set_child(new_right, 1);
    new_right->set_parent(root);

    root->set_rake(nullptr);

    new_right->fix();
    root->fix();
  }
  else if(rake->type() == Type::Rake) {
    rake->push();
    while(rake->child(1)->type() == Type::Rake) {
      rake->child(1)->push();
      rake = rake->child(1);
    }
    root->guard = true;
    splay(rake);
    root->guard = false;

    node* new_rake = rake->child(0);
    node* new_right = rake->child(1);

    //delete rake, rake = nullptr;
    new_right->reverse();
    new_right->push();

    root->set_child(new_right, 1);
    new_right->set_parent(root);

    root->set_rake(new_rake);
    new_rake->set_parent(root);

    new_rake->fix();
    new_right->fix();
    root->fix();
  }
}

void cut(vertex v, vertex u) {
  soft_expose(v, u);
  node* root = v.handle();
  root->push();
  node* right = root->child(1);
  right->set_parent(nullptr);

  right->reverse();
  right->push();

  bring(right);
  bring(root);
}

cluster path_query(vertex v, vertex u) {
  soft_expose(v, u);
  node* root = v.handle();
  root->push();
  if(root->endpoint(0) == v && root->endpoint(1) == u) {
    return root->fold();
  }
  else if(root->endpoint(0) == v) {
    return root->child(0)->fold();
  }
  else if(root->endpoint(1) == u) {
    return root->child(1)->fold();
  }
  else {
    root->child(1)->push();
    return root->child(1)->child(0)->fold();
  }
}

node* select_rake(node* rake, cluster& right, cluster::V& rv0, cluster::V& rv1) {
  rake->push();
  while(rake->type() == Type::Rake) {
    node* l = rake->child(0);
    node* r = rake->child(1);
    l->push();
    r->push();

    cluster rf = cluster::rake(r->fold(), right, r->endpoint(0).value(), rv0, r->endpoint(1).value());
    cluster::V r0 = r->endpoint(0).value();

    std::size_t dir = cluster::select(l->fold(), rf, l->endpoint(0).value(), r0, l->endpoint(1).value());
    r = rake->child(1 - dir);
    rake = rake->child(dir);


    right = cluster::rake(r->fold(), right, r->endpoint(0).value(), rv0, r->endpoint(1).value());
    rv0 = r->endpoint(0).value();
    rv1 = r->endpoint(1).value();

    rake->push();
  }
  return rake;
}

std::pair<vertex, vertex> select(vertex v) {
  node* n = expose(v);
  cluster lf = cluster::identity();
  cluster::V l0, l1;
  bool luse = false;
  cluster rf = cluster::identity();
  cluster::V r0, r1;
  bool ruse = false;

  n->push();
  while(n->type() == Type::Compress) {
    node* a = n->child(0);
    node* b = n->child(1);
    node* r = n->rake();
    a->push();
    b->push();
    if(r) { r->push(); }

    cluster af = a->fold();
    cluster::V a0 = a->endpoint(0).value();
    cluster::V a1 = a->endpoint(1).value();
    if(luse) {
      af = cluster::compress(lf, af, l0, a1, l1);
      a0 = l0;
      a1 = a1;
    }
    cluster bf = b->fold();
    cluster::V b0 = b->endpoint(0).value();
    cluster::V b1 = b->endpoint(1).value();
    if(ruse) {
      bf = cluster::compress(bf, rf, b0, r1, b1);
      b0 = b0;
      b1 = r1;
    }
    cluster arf = af;
    if(r) {
      arf = cluster::rake(af, r->fold(), a0, r->endpoint(0).value(), a1);
    }

    std::size_t dir = cluster::select(arf, bf, a0, b1, a1);
    
    if(dir == 0) {
      if(r) {
        cluster rbf = cluster::reverse(bf);
        cluster::V rb0 = b1;

        cluster rrf = cluster::rake(r->fold(), rbf, r->endpoint(0).value(), rb0, r->endpoint(1).value());
        cluster::V rr0 = r->endpoint(0).value();
        cluster::V rr1 = r->endpoint(1).value();

        dir = cluster::select(af, rrf, a0, rr0, a1);
        if(dir == 0) {
          rf = cluster::reverse(rrf);
          r0 = rr1;
          r1 = rr0;
          ruse = true;
          n = n->child(0);
        }
        else {
          luse = false;
          rf = cluster::rake(af, rbf, a0, rb0, a1);
          r0 = a0;
          r1 = a1;
          ruse = true;
          n = select_rake(r, rf, r0, r1);
          rf = cluster::reverse(rf);
          std::swap(r0, r1);
        }
      }
      else {
        rf = bf;
        r0 = b0;
        r1 = b1;
        ruse = true;
        n = n->child(0);
      }
    }
    else {
      lf = arf;
      l0 = a0;
      l1 = a1;
      luse = true;
      n = n->child(1);
    }

    n->push();
  }
  return { n->endpoint(0), n->endpoint(1) };
}

node ns[1515151];

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
#define all(x) x.begin(),x.end()

template<class T>
static inline std::vector<T> ndvec(size_t&& n, T val) noexcept {
  return std::vector<T>(n, std::forward<T>(val));
}

template<class... Tail>
static inline auto ndvec(size_t&& n, Tail&&... tail) noexcept {
  return std::vector<decltype(ndvec(std::forward<Tail>(tail)...))>(n, ndvec(std::forward<Tail>(tail)...));
}

template<class T, class Cond>
struct chain {
  Cond cond; chain(Cond cond) : cond(cond) {}
  bool operator()(T& a, const T& b) const {
    if(cond(a, b)) { a = b; return true; }
    return false;
  }
};
#include <iostream>
#include <vector>
#include <tuple>

using namespace std;

#include <cstdio>

namespace niu {
  char cur;
  struct FIN {
    static inline bool is_blank(char c) { return c <= ' '; }
    inline char next() { return cur = getc_unlocked(stdin); }
    inline char peek() { return cur; }
    inline void skip() { while(is_blank(next())){} }
#define intin(inttype)  \
    FIN& operator>>(inttype& n) { \
      bool sign = 0; \
      n = 0; \
      skip(); \
      while(!is_blank(peek())) { \
        if(peek() == '-') sign = 1; \
        else n = (n << 1) + (n << 3) + (peek() & 0b1111); \
        next(); \
      } \
      if(sign) n = -n; \
      return *this; \
    }
intin(int)
intin(long long)
  } fin;

  char tmp[128];
  struct FOUT {
    static inline bool is_blank(char c) { return c <= ' '; }
    inline void push(char c) { putc_unlocked(c, stdout); }
    FOUT& operator<<(char c) { push(c); return *this; }
    FOUT& operator<<(const char* s) { while(*s) push(*s++); return *this; }
#define intout(inttype) \
    FOUT& operator<<(inttype n) { \
      if(n) { \
        char* p = tmp + 127; bool neg = 0; \
        if(n < 0) neg = 1, n = -n; \
        while(n) *--p = (n % 10) | 0b00110000, n /= 10; \
        if(neg) *--p = '-'; \
        return (*this) << p; \
      } \
      else { \
        push('0'); \
        return *this; \
      } \
    }
intout(int)
intout(long long)
  } fout;
}

template<class T, class Cond>
chain<T, Cond> make_chain(Cond cond) { return chain<T, Cond>(cond); }
int main() {
  using niu::fin;
  using niu::fout;
  i64 N, Q;
  fin >> N;
  vector<vertex> vs(N);
  vector<i64> leaf(N);
  for(int i = 0;i < N;i++) {
    vs[i] = vertex(0);
  }
  vector<int> A(N - 1), B(N - 1), D(N - 1);
  for(int i = 0;i + 1 < N;i++) {
    fin >> A[i] >> B[i] >> D[i];
    A[i]--;
    B[i]--;
    link(vs[A[i]], vs[B[i]], cluster(D[i], A[i], B[i]));
    leaf[A[i]] += i;
    leaf[B[i]] += i;
  }
  fin >> Q;
  int now = 0;
  vector<int> ans(N);
  for(int i = 0;i < Q;i++) {
    int c, x;
    fin >> c >> x;
    x--;
    if(c == 1) {
      now = x;
    }
    else if(c == 2) {
      cut(vs[A[x]], vs[B[x]]);
      leaf[A[x]] -= x;
      leaf[B[x]] -= x;
    }
    else {
      link(vs[A[x]], vs[B[x]], cluster(D[x], A[x], B[x]));
      leaf[A[x]] += x;
      leaf[B[x]] += x;
    }
    i64 MAX = expose(vs[now])->fold().ans.d;
    if(MAX == 0) {
      fout << 1 << " " << now + 1 << '\n';
      continue;
    }
    int ai = 0;
    while(true) {
      auto res = expose(vs[now])->fold().ans;
      if(res.d < MAX) break;
      ans[ai++] = res.to;
      int idx = leaf[res.to];
      cut(vs[A[idx]], vs[B[idx]]);
    }

    sort(begin(ans), begin(ans) + ai);
    fout << ai;
    rep(j,0,ai) fout << ' ' << ans[j] + 1;
    fout << '\n';
    rep(j,0,ai)  {
      int idx = leaf[ans[j]];
      link(vs[A[idx]], vs[B[idx]], cluster(D[idx], A[idx], B[idx]));
    }
  }
}
accuracy: 0.30666666666666664
time_ms: 1110
memory_kb: 210848
final_rank: 10

code_snippet: #ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#endif
//BEGIN CUT HERE
struct Vertex{
  void* handle;
  int idx;
  Vertex(int idx=-1):handle(nullptr),idx(idx){}
};

template<typename T>
struct Farthest{
  struct pi{
    T dist;
    int idx;
    pi():dist(0),idx(-1){}
    pi(T dist,int idx):dist(dist),idx(idx){}
    bool operator<(const pi &o)const{return dist<o.dist;}
    pi operator+(const T e)const{return pi(dist+e,idx);}
  };
  pi md,lf,rg;
  T len;
  Farthest(){}
  Farthest(T l,int f,int t):lf(l,t),rg(l,f),len(l){}
  Farthest(pi md,pi lf,pi rg,T len):
    md(md),lf(lf),rg(rg),len(len){}
  void toggle(){swap(lf,rg);}
  static Farthest compress(Farthest x,Vertex*,Farthest y){
    return Farthest(
      max(x.rg,y.lf),
      max(x.lf,y.lf+x.len),
      max(y.rg,x.rg+y.len),
      x.len+y.len);
  }
  static Farthest rake(Farthest x,Farthest y,Vertex*){
    return Farthest(pi(),max(x.lf,y.rg+x.len),max(x.rg,y.rg),x.len);
  }
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE

#define call_from_test
#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename Vertex, typename Cluster, size_t LIM>
struct TopTree{
  enum Type { Compress, Rake, Edge, None };
  struct Node{
    Vertex* vs[2];
    Cluster dat;
    Node* p;
    Node* q;
    Node* ch[2];
    bool rev,guard;
    Type type;
    Node():p(nullptr),q(nullptr),rev(false),guard(false),type(Type::None){}
  };

  static array<Vertex, LIM> pool_v;
  static array<Node, LIM> pool_c;
  size_t ptr_v,ptr_c;

  Cluster id;
  TopTree(Cluster id=Cluster()):ptr_v(0),ptr_c(0),id(id){}

  inline Vertex* create(Vertex v){
    assert(ptr_v+1<LIM);
    auto t=&pool_v[ptr_v++];
    auto dummy=&pool_v[ptr_v++];
    *t=v;
    link(t,id,dummy);
    return t;
  }

  inline Node* edge(Vertex* u,Cluster w,Vertex* v){
    assert(ptr_c<LIM);
    auto t=&(pool_c[ptr_c++]);
    t->vs[0]=u;t->vs[1]=v;t->dat=w;t->type=Type::Edge;
    return pushup(t);
  }

  inline Node* compress(Node* l,Node* r){
    assert(ptr_c<LIM);
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Compress;
    return pushup(t);
  }

  inline Node* rake(Node* l,Node* r){
    assert(ptr_c<LIM);
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Rake;
    return pushup(t);
  }

  int parent_dir(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->guard) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  inline Node* pushup(Node* const t){
    Node* const l=t->ch[0];
    Node* const r=t->ch[1];

    if(t->type==Type::Edge){
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }else if(t->type==Type::Compress){
      assert(l->vs[1]==r->vs[0]);
      t->vs[0]=l->vs[0];
      t->vs[1]=r->vs[1];

      Cluster lf=l->dat;
      if(t->q){
        Node* q=t->q;
        assert(l->vs[1]==q->vs[1]);
        lf=Cluster::rake(l->dat,q->dat,q->vs[0]);
      }
      t->dat=Cluster::compress(lf,r->vs[0],r->dat);

      l->vs[1]->handle=t;
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }else if(t->type==Type::Rake){
      propagate(t);
      assert(l->vs[1]==r->vs[1]);
      t->vs[0]=l->vs[0];
      t->vs[1]=l->vs[1];
      t->dat=Cluster::rake(l->dat,r->dat,r->vs[0]);
    }else abort();
    return t;
  }


  int parent_dir_ignore_guard(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  void rotate(Node* t,Node* x,size_t dir){
    Node* y=x->p;
    int par=parent_dir_ignore_guard(x);
    propagate(t->ch[dir]);
    x->ch[dir^1]=t->ch[dir];
    t->ch[dir]->p=x;
    t->ch[dir]=x;
    x->p=t;
    t->p=y;
    if(~par) y->ch[par]=t;
    else if(y and y->type==Type::Compress) y->q=t;
    pushup(x);pushup(t);
    if(y and !y->guard) pushup(y);
  }

  inline void propagate(Node* t){
    if(t->type==Type::Compress){
      if(t->rev){
        assert(t->ch[0] and t->ch[1]);
        swap(t->ch[0],t->ch[1]);
        toggle(t->ch[0]);
        toggle(t->ch[1]);
        t->rev=false;
      }
    }
  }

  inline void toggle(Node* t){
    if(t->type==Type::Edge){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
    }else if(t->type==Type::Compress){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
      t->rev^=true;
    }else if(t->type==Type::Rake){
    }else abort();
  }

  void splay(Node* t){
    assert(t->type!=Type::Edge);
    propagate(t);

    while(~parent_dir(t)){
      Node* q=t->p;
      if(q->type!=t->type) break;
      if(~parent_dir(q) and q->p and q->p->type==q->type){
        Node* r=q->p;
        if(r->p) propagate(r->p);
        propagate(r);propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        int rq_dir=parent_dir(q);
        if(rq_dir==qt_dir){
          rotate(q,r,rq_dir^1);
          rotate(t,q,qt_dir^1);
        }else{
          rotate(t,q,qt_dir^1);
          rotate(t,r,rq_dir^1);
        }
      }else{
        if(q->p) propagate(q->p);
        propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        rotate(t,q,qt_dir^1);
      }
    }
  }

  void pushdown(Node* t){
    if(!t) return;
    pushdown(t->p);
    propagate(t);
  }

  Node* expose(Node* t){
    pushdown(t);
    while(true){
      assert(t->type!=Type::Rake);
      if(t->type==Type::Compress) splay(t);
      Node* n=nullptr;
      {
        Node* p=t->p;
        if(!p) break;
        if(p->type==Type::Rake){
          propagate(p);
          splay(p);
          n=p->p;
        }else if(p->type==Type::Compress){
          propagate(p);
          if(p->guard and ~parent_dir_ignore_guard(t)) break;
          n=p;
        }else abort();
      }
      splay(n);
      int dir=parent_dir_ignore_guard(n);
      if(dir==-1 or n->p->type==Type::Rake) dir=0;

      Node* const c=n->ch[dir];
      if(dir==1){
        toggle(c);
        propagate(c);
        toggle(t);
        propagate(t);
      }
      int n_dir=parent_dir(t);
      if(~n_dir){
        propagate(c);
        Node* const r=t->p;
        propagate(r);
        r->ch[n_dir]=c;
        c->p=r;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(r);pushup(t);pushup(n);
        splay(r);
      }else{
        propagate(c);
        n->q=c;
        c->p=n;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(t);pushup(n);
      }
      if(t->type==Type::Edge) t=n;
    }
    return t;
  }

  Node* expose(Vertex* v){
    return expose((Node*)(v->handle));
  }

  Node* link(Vertex* u,Cluster w,Vertex* v){
    if(!u->handle and !v->handle) return edge(u,w,v);

    Node* nnu=(Node*)u->handle;
    Node* nnv=(Node*)v->handle;
    Node* ee=edge(u,w,v);
    Node* ll=nullptr;

    if(!nnv) ll=ee;
    else{
      Node* vv=expose(nnv);
      propagate(vv);
      if(vv->vs[1]==v){
        toggle(vv);
        propagate(vv);
      }
      if(vv->vs[0]==v){
        Node* nv=compress(ee,vv);
        ee->p=nv;
        pushup(ee);
        vv->p=nv;
        pushup(vv);pushup(nv);
        ll=nv;
      }else{
        Node* nv=vv;
        Node* ch=nv->ch[0];
        propagate(ch);
        nv->ch[0]=ee;
        ee->p=nv;
        pushup(ee);

        Node* bt=nv->q;
        Node* rk=nullptr;
        if(bt){
          propagate(bt);
          rk=rake(bt,ch);
          bt->p=rk;
          ch->p=rk;
          pushup(bt);pushup(ch);
        }else{
          rk=ch;
        }
        nv->q=rk;
        rk->p=nv;
        pushup(rk);pushup(nv);
        ll=nv;
      }
    }

    if(nnu){
      Node* uu=expose(nnu);
      propagate(uu);
      if(uu->vs[0]==u){
        toggle(uu);
        propagate(uu);
      }
      if(uu->vs[1]==u){
        Node* tp=compress(uu,ll);
        uu->p=tp;
        ll->p=tp;
        pushup(uu);pushup(ll);pushup(tp);
      }else{
        Node* nu=uu;
        Node* ch=nu->ch[1];
        toggle(ch);
        propagate(ch);

        nu->ch[1]=ll;
        ll->p=nu;
        pushup(ll);

        Node* al=nu->q;
        Node* rk=nullptr;
        if(al){
          propagate(al);
          rk=rake(al,ch);
          al->p=rk;
          ch->p=rk;
          pushup(al);pushup(ch);
        }else{
          rk=ch;
        }
        nu->q=rk;
        rk->p=nu;
        pushup(rk);pushup(nu);
      }
    }
    return ee;
  }

  void set_toggle(Node* v){
    toggle(v);propagate(v);
  }

  void soft_expose(Vertex* u,Vertex* v){
    pushdown((Node*)u->handle);
    pushdown((Node*)v->handle);
    Node* rt=expose((Node*)u->handle);

    if(u->handle==v->handle){
      if(rt->vs[1]==u or rt->vs[0]==v)
        set_toggle(rt);
      return;
    }

    rt->guard=true;
    Node* soft=expose((Node*)v->handle);
    rt->guard=false;

    pushup(rt);
    if(parent_dir(soft)==0) set_toggle(rt);
  }

  void set_val(Vertex* u,Vertex v){
    auto t=expose(u);
    *u=v;
    pushup(t);
  }

  Cluster query(Vertex* u,Vertex* v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);

    if(rt->vs[0]==u and rt->vs[1]==v) return rt->dat;
    if(rt->vs[0]==u) return rt->ch[0]->dat;
    if(rt->vs[1]==v) return rt->ch[1]->dat;
    propagate(rt->ch[1]);
    return rt->ch[1]->ch[0]->dat;
  }

  void bring(Node* rt){
    Node* rk=rt->q;
    if(!rk){
      Node* ll=rt->ch[0];
      ll->p=nullptr;
      pushup(ll);
    }else if(rk->type==Type::Compress or rk->type==Type::Edge){
      propagate(rk);

      Node* nr=rk;
      set_toggle(nr);
      rt->ch[1]=nr;
      nr->p=rt;
      rt->q=nullptr;

      pushup(nr);pushup(rt);
    }else if(rk->type==Type::Rake){
      propagate(rk);
      while(rk->ch[1]->type==Type::Rake){
        propagate(rk->ch[1]);
        rk=rk->ch[1];
      }
      pushdown(rk);

      rt->guard=true;
      splay(rk);
      rt->guard=false;

      Node* ll=rk->ch[0];
      Node* rr=rk->ch[1];
      propagate(ll);
      set_toggle(rr);

      rt->ch[1]=rr;
      rr->p=rt;

      rt->q=ll;
      ll->p=rt;

      pushup(ll);pushup(rr);pushup(rt);
    }
  }

  void cut(Vertex* u,Vertex *v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    Node* rr=rt->ch[1];
    rr->p=nullptr;
    set_toggle(rr);
    bring(rr);bring(rt);
  }

  Cluster subtree(Vertex* p,Vertex* v){
    Cluster e=query(p,v);
    cut(p,v);
    expose(v);
    Node* t=(Node*)v->handle;
    Cluster res=t->dat;
    if(t->type==Type::Edge)
      res=Cluster::rake(res,id,v);
    link(p,e,v);
    return res;
  }
};
template<typename Vertex, typename Cluster, size_t LIM>
array<Vertex, LIM> TopTree<Vertex, Cluster, LIM>::pool_v;
template<typename Vertex, typename Cluster, size_t LIM>
array<typename TopTree<Vertex, Cluster, LIM>::Node, LIM>
TopTree<Vertex, Cluster, LIM>::pool_c;
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#undef call_from_test

signed KUPC2020_G(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  const char newl = '\n';

  const size_t LIM = 1.5e6;
  using Cluster = Farthest<long long>;
  TopTree<Vertex, Cluster, LIM> T(Cluster(0,-1,-1));

  int n;
  cin>>n;

  vector<Vertex*> vs(n);
  for(int i=0;i<n;i++)
    vs[i]=T.create(Vertex(i));

  vector<int> as(n),bs(n),ds(n);
  vector<set<int>> S(n);
  for(int i=1;i<n;i++){
    cin>>as[i]>>bs[i]>>ds[i];
    as[i]--;bs[i]--;
    S[as[i]].emplace(i);
    S[bs[i]].emplace(i);
    T.link(vs[as[i]],Cluster(ds[i],as[i],bs[i]),vs[bs[i]]);
  }

  int q;
  cin>>q;

  int cur=0;
  for(int i=0;i<q;i++){
    int t;
    cin>>t;
    if(t==1){
      int x;
      cin>>x;
      x--;
      cur=x;
    }
    if(t==2){
      int y;
      cin>>y;
      S[as[y]].erase(y);
      S[bs[y]].erase(y);
      T.cut(vs[as[y]],vs[bs[y]]);
    }
    if(t==3){
      int z;
      cin>>z;
      S[as[z]].emplace(z);
      S[bs[z]].emplace(z);
      T.link(vs[as[z]],Cluster(ds[z],as[z],bs[z]),vs[bs[z]]);
    }
    auto dist=T.expose(vs[cur])->dat.md.dist;
    if(dist==0){
      cout<<1<<" "<<cur+1<<newl;
      continue;
    }
    vector<int> ans;
    while(1){
      auto res=T.expose(vs[cur])->dat.md;
      if(dist!=res.dist) break;
      ans.emplace_back(res.idx);
      int k=*S[res.idx].begin();
      T.cut(vs[as[k]],vs[bs[k]]);
    }

    sort(ans.begin(),ans.end());
    cout<<ans.size();
    for(int v:ans) cout<<" "<<v+1;
    cout<<newl;

    for(int v:ans){
      int k=*S[v].begin();
      T.link(vs[as[k]],Cluster(ds[k],as[k],bs[k]),vs[bs[k]]);
    }
  }

  return 0;
}

signed main(){
  KUPC2020_G();
  return 0;
}
#endif
accuracy: 0.30666666666666664
time_ms: 1450
memory_kb: 224612
final_rank: 12

code_snippet: #ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;

#endif
//BEGIN CUT HERE
struct Vertex{
  void* handle;
  int idx;
  Vertex(int idx=-1):handle(nullptr),idx(idx){}
};

template<typename T>
struct Farthest{
  struct pi{
    T dist;
    int idx;
    pi():dist(0),idx(-1){}
    pi(T dist,int idx):dist(dist),idx(idx){}
    bool operator<(const pi &o)const{return dist<o.dist;}
    pi operator+(const T e)const{return pi(dist+e,idx);}
  };
  pi md,lf,rg;
  T len;
  Farthest(){}
  Farthest(T l,int f,int t):lf(l,t),rg(l,f),len(l){}
  Farthest(pi md,pi lf,pi rg,T len):
    md(md),lf(lf),rg(rg),len(len){}
  void toggle(){swap(lf,rg);}
  static Farthest compress(Farthest x,Vertex*,Farthest y){
    return Farthest(
      max(x.rg,y.lf),
      max(x.lf,y.lf+x.len),
      max(y.rg,x.rg+y.len),
      x.len+y.len);
  }
  static Farthest rake(Farthest x,Farthest y,Vertex*){
    return Farthest(pi(),max(x.lf,y.rg+x.len),max(x.rg,y.rg),x.len);
  }
};
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE

#define call_from_test
#ifndef call_from_test
#include <bits/stdc++.h>
using namespace std;
#endif
//BEGIN CUT HERE
template<typename Vertex, typename Cluster, size_t LIM>
struct TopTree{
  enum Type { Compress, Rake, Edge, None };
  struct Node{
    Vertex* vs[2];
    Cluster dat;
    Node* p;
    Node* q;
    Node* ch[2];
    bool rev,guard;
    Type type;
    Node():p(nullptr),q(nullptr),rev(false),guard(false),type(Type::None){}
  };

  static array<Vertex, LIM> pool_v;
  static array<Node, LIM> pool_c;
  size_t ptr_v,ptr_c;

  Cluster id;
  TopTree(Cluster id=Cluster()):ptr_v(0),ptr_c(0),id(id){}

  inline Vertex* create(Vertex v){
    auto t=&pool_v[ptr_v++];
    auto dummy=&pool_v[ptr_v++];
    *t=v;
    link(t,id,dummy);
    return t;
  }

  inline Node* edge(Vertex* u,Cluster w,Vertex* v){
    auto t=&(pool_c[ptr_c++]);
    t->vs[0]=u;t->vs[1]=v;t->dat=w;t->type=Type::Edge;
    return pushup(t);
  }

  inline Node* compress(Node* l,Node* r){
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Compress;
    return pushup(t);
  }

  inline Node* rake(Node* l,Node* r){
    auto t=&(pool_c[ptr_c++]);
    t->ch[0]=l;t->ch[1]=r;t->type=Type::Rake;
    return pushup(t);
  }

  int parent_dir(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->guard) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  inline Node* pushup(Node* const t){
    Node* const l=t->ch[0];
    Node* const r=t->ch[1];

    if(t->type==Type::Edge){
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }else if(t->type==Type::Compress){
      assert(l->vs[1]==r->vs[0]);
      t->vs[0]=l->vs[0];
      t->vs[1]=r->vs[1];

      Cluster lf=l->dat;
      if(t->q){
        Node* q=t->q;
        assert(l->vs[1]==q->vs[1]);
        lf=Cluster::rake(l->dat,q->dat,q->vs[0]);
      }
      t->dat=Cluster::compress(lf,r->vs[0],r->dat);

      l->vs[1]->handle=t;
      if(!t->p){
        t->vs[0]->handle=t;
        t->vs[1]->handle=t;
      }else if(t->p->type==Type::Compress){
        if(parent_dir(t)==-1)
          t->vs[0]->handle=t;
      }else if(t->p->type==Type::Rake){
        t->vs[0]->handle=t;
      }
    }else if(t->type==Type::Rake){
      propagate(t);
      assert(l->vs[1]==r->vs[1]);
      t->vs[0]=l->vs[0];
      t->vs[1]=l->vs[1];
      t->dat=Cluster::rake(l->dat,r->dat,r->vs[0]);
    }else abort();
    return t;
  }


  int parent_dir_ignore_guard(Node* t){
    Node* p=t->p;
    if(!p) return -1;
    if(p->ch[0]==t) return 0;
    if(p->ch[1]==t) return 1;
    return -1;
  }

  void rotate(Node* t,Node* x,size_t dir){
    Node* y=x->p;
    int par=parent_dir_ignore_guard(x);
    propagate(t->ch[dir]);
    x->ch[dir^1]=t->ch[dir];
    t->ch[dir]->p=x;
    t->ch[dir]=x;
    x->p=t;
    t->p=y;
    if(~par) y->ch[par]=t;
    else if(y and y->type==Type::Compress) y->q=t;
    pushup(x);pushup(t);
    if(y and !y->guard) pushup(y);
  }

  inline void propagate(Node* t){
    if(t->type==Type::Compress){
      if(t->rev){
        assert(t->ch[0] and t->ch[1]);
        swap(t->ch[0],t->ch[1]);
        toggle(t->ch[0]);
        toggle(t->ch[1]);
        t->rev=false;
      }
    }
  }

  inline void toggle(Node* t){
    if(t->type==Type::Edge){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
    }else if(t->type==Type::Compress){
      swap(t->vs[0],t->vs[1]);
      t->dat.toggle();
      t->rev^=true;
    }else if(t->type==Type::Rake){
    }else abort();
  }

  void splay(Node* t){
    assert(t->type!=Type::Edge);
    propagate(t);

    while(~parent_dir(t)){
      Node* q=t->p;
      if(q->type!=t->type) break;
      if(~parent_dir(q) and q->p and q->p->type==q->type){
        Node* r=q->p;
        if(r->p) propagate(r->p);
        propagate(r);propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        int rq_dir=parent_dir(q);
        if(rq_dir==qt_dir){
          rotate(q,r,rq_dir^1);
          rotate(t,q,qt_dir^1);
        }else{
          rotate(t,q,qt_dir^1);
          rotate(t,r,rq_dir^1);
        }
      }else{
        if(q->p) propagate(q->p);
        propagate(q);propagate(t);
        int qt_dir=parent_dir(t);
        rotate(t,q,qt_dir^1);
      }
    }
  }

  void pushdown(Node* t){
    if(!t) return;
    pushdown(t->p);
    propagate(t);
  }

  Node* expose(Node* t){
    pushdown(t);
    while(true){
      assert(t->type!=Type::Rake);
      if(t->type==Type::Compress) splay(t);
      Node* n=nullptr;
      {
        Node* p=t->p;
        if(!p) break;
        if(p->type==Type::Rake){
          propagate(p);
          splay(p);
          n=p->p;
        }else if(p->type==Type::Compress){
          propagate(p);
          if(p->guard and ~parent_dir_ignore_guard(t)) break;
          n=p;
        }else abort();
      }
      splay(n);
      int dir=parent_dir_ignore_guard(n);
      if(dir==-1 or n->p->type==Type::Rake) dir=0;

      Node* const c=n->ch[dir];
      if(dir==1){
        toggle(c);
        propagate(c);
        toggle(t);
        propagate(t);
      }
      int n_dir=parent_dir(t);
      if(~n_dir){
        propagate(c);
        Node* const r=t->p;
        propagate(r);
        r->ch[n_dir]=c;
        c->p=r;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(r);pushup(t);pushup(n);
        splay(r);
      }else{
        propagate(c);
        n->q=c;
        c->p=n;
        n->ch[dir]=t;
        t->p=n;
        pushup(c);pushup(t);pushup(n);
      }
      if(t->type==Type::Edge) t=n;
    }
    return t;
  }

  Node* expose(Vertex* v){
    return expose((Node*)(v->handle));
  }

  Node* link(Vertex* u,Cluster w,Vertex* v){
    if(!u->handle and !v->handle) return edge(u,w,v);

    Node* nnu=(Node*)u->handle;
    Node* nnv=(Node*)v->handle;
    Node* ee=edge(u,w,v);
    Node* ll=nullptr;

    if(!nnv) ll=ee;
    else{
      Node* vv=expose(nnv);
      propagate(vv);
      if(vv->vs[1]==v){
        toggle(vv);
        propagate(vv);
      }
      if(vv->vs[0]==v){
        Node* nv=compress(ee,vv);
        ee->p=nv;
        pushup(ee);
        vv->p=nv;
        pushup(vv);pushup(nv);
        ll=nv;
      }else{
        Node* nv=vv;
        Node* ch=nv->ch[0];
        propagate(ch);
        nv->ch[0]=ee;
        ee->p=nv;
        pushup(ee);

        Node* bt=nv->q;
        Node* rk=nullptr;
        if(bt){
          propagate(bt);
          rk=rake(bt,ch);
          bt->p=rk;
          ch->p=rk;
          pushup(bt);pushup(ch);
        }else{
          rk=ch;
        }
        nv->q=rk;
        rk->p=nv;
        pushup(rk);pushup(nv);
        ll=nv;
      }
    }

    if(nnu){
      Node* uu=expose(nnu);
      propagate(uu);
      if(uu->vs[0]==u){
        toggle(uu);
        propagate(uu);
      }
      if(uu->vs[1]==u){
        Node* tp=compress(uu,ll);
        uu->p=tp;
        ll->p=tp;
        pushup(uu);pushup(ll);pushup(tp);
      }else{
        Node* nu=uu;
        Node* ch=nu->ch[1];
        toggle(ch);
        propagate(ch);

        nu->ch[1]=ll;
        ll->p=nu;
        pushup(ll);

        Node* al=nu->q;
        Node* rk=nullptr;
        if(al){
          propagate(al);
          rk=rake(al,ch);
          al->p=rk;
          ch->p=rk;
          pushup(al);pushup(ch);
        }else{
          rk=ch;
        }
        nu->q=rk;
        rk->p=nu;
        pushup(rk);pushup(nu);
      }
    }
    return ee;
  }

  void set_toggle(Node* v){
    toggle(v);propagate(v);
  }

  void soft_expose(Vertex* u,Vertex* v){
    pushdown((Node*)u->handle);
    pushdown((Node*)v->handle);
    Node* rt=expose((Node*)u->handle);

    if(u->handle==v->handle){
      if(rt->vs[1]==u or rt->vs[0]==v)
        set_toggle(rt);
      return;
    }

    rt->guard=true;
    Node* soft=expose((Node*)v->handle);
    rt->guard=false;

    pushup(rt);
    if(parent_dir(soft)==0) set_toggle(rt);
  }

  void set_val(Vertex* u,Vertex v){
    auto t=expose(u);
    *u=v;
    pushup(t);
  }

  Cluster query(Vertex* u,Vertex* v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);

    if(rt->vs[0]==u and rt->vs[1]==v) return rt->dat;
    if(rt->vs[0]==u) return rt->ch[0]->dat;
    if(rt->vs[1]==v) return rt->ch[1]->dat;
    propagate(rt->ch[1]);
    return rt->ch[1]->ch[0]->dat;
  }

  void bring(Node* rt){
    Node* rk=rt->q;
    if(!rk){
      Node* ll=rt->ch[0];
      ll->p=nullptr;
      pushup(ll);
    }else if(rk->type==Type::Compress or rk->type==Type::Edge){
      propagate(rk);

      Node* nr=rk;
      set_toggle(nr);
      rt->ch[1]=nr;
      nr->p=rt;
      rt->q=nullptr;

      pushup(nr);pushup(rt);
    }else if(rk->type==Type::Rake){
      propagate(rk);
      while(rk->ch[1]->type==Type::Rake){
        propagate(rk->ch[1]);
        rk=rk->ch[1];
      }
      pushdown(rk);

      rt->guard=true;
      splay(rk);
      rt->guard=false;

      Node* ll=rk->ch[0];
      Node* rr=rk->ch[1];
      propagate(ll);
      set_toggle(rr);

      rt->ch[1]=rr;
      rr->p=rt;

      rt->q=ll;
      ll->p=rt;

      pushup(ll);pushup(rr);pushup(rt);
    }
  }

  void cut(Vertex* u,Vertex *v){
    soft_expose(u,v);
    Node* rt=(Node*)u->handle;
    propagate(rt);
    Node* rr=rt->ch[1];
    rr->p=nullptr;
    set_toggle(rr);
    bring(rr);bring(rt);
  }

  Cluster subtree(Vertex* p,Vertex* v){
    Cluster e=query(p,v);
    cut(p,v);
    expose(v);
    Node* t=(Node*)v->handle;
    Cluster res=t->dat;
    if(t->type==Type::Edge)
      res=Cluster::rake(res,id,v);
    link(p,e,v);
    return res;
  }
};
template<typename Vertex, typename Cluster, size_t LIM>
array<Vertex, LIM> TopTree<Vertex, Cluster, LIM>::pool_v;
template<typename Vertex, typename Cluster, size_t LIM>
array<typename TopTree<Vertex, Cluster, LIM>::Node, LIM>
TopTree<Vertex, Cluster, LIM>::pool_c;
//END CUT HERE
#ifndef call_from_test
//INSERT ABOVE HERE
signed main(){
  return 0;
}
#endif

#undef call_from_test

signed KUPC2020_G(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  const char newl = '\n';

  const size_t LIM = 1.5e6;
  using Cluster = Farthest<long long>;
  TopTree<Vertex, Cluster, LIM> T(Cluster(0,-1,-1));

  int n;
  cin>>n;

  vector<Vertex*> vs(n);
  for(int i=0;i<n;i++)
    vs[i]=T.create(Vertex(i));

  vector<int> as(n),bs(n),ds(n);
  vector<set<int>> S(n);
  for(int i=1;i<n;i++){
    cin>>as[i]>>bs[i]>>ds[i];
    as[i]--;bs[i]--;
    S[as[i]].emplace(i);
    S[bs[i]].emplace(i);
    T.link(vs[as[i]],Cluster(ds[i],as[i],bs[i]),vs[bs[i]]);
  }

  int q;
  cin>>q;

  int cur=0;
  for(int i=0;i<q;i++){
    int t;
    cin>>t;
    if(t==1){
      int x;
      cin>>x;
      x--;
      cur=x;
    }
    if(t==2){
      int y;
      cin>>y;
      S[as[y]].erase(y);
      S[bs[y]].erase(y);
      T.cut(vs[as[y]],vs[bs[y]]);
    }
    if(t==3){
      int z;
      cin>>z;
      S[as[z]].emplace(z);
      S[bs[z]].emplace(z);
      T.link(vs[as[z]],Cluster(ds[z],as[z],bs[z]),vs[bs[z]]);
    }
    auto dist=T.expose(vs[cur])->dat.md.dist;
    if(dist==0){
      cout<<1<<" "<<cur+1<<newl;
      continue;
    }
    vector<int> ans;
    while(1){
      auto res=T.expose(vs[cur])->dat.md;
      if(dist!=res.dist) break;
      ans.emplace_back(res.idx);
      int k=*S[res.idx].begin();
      T.cut(vs[as[k]],vs[bs[k]]);
    }

    sort(ans.begin(),ans.end());
    cout<<ans.size();
    for(int v:ans) cout<<" "<<v+1;
    cout<<newl;

    for(int v:ans){
      int k=*S[v].begin();
      T.link(vs[as[k]],Cluster(ds[k],as[k],bs[k]),vs[bs[k]]);
    }
  }

  return 0;
}

signed main(){
  KUPC2020_G();
  return 0;
}
#endif
accuracy: 0.30666666666666664
time_ms: 1420
memory_kb: 224476
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;

using int64 = long long;
const int mod = 998244353;

const int64 infll = (1LL << 60) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}


template< class T, size_t V >
struct ArrayPool {
  array< T, V > pool;
  array< T *, V > stock;
  int ptr;

  ArrayPool() { clear(); }

  inline T *alloc() {
    return stock[--ptr];
  }

  inline void free(T *t) {
    stock[ptr++] = t;
  }

  void clear() {
    ptr = (int) pool.size();
    for(int i = 0; i < pool.size(); i++) stock[i] = &pool[i];
  }
};


struct pi {
  int64 first;
  int second;

  pi(const int64 &first, const int &second) : first(first), second(second) {}

  pi() = default;

  bool operator<(const pi &a) const {
    if(first != a.first) return first < a.first;
    return true;
  }

  bool operator>(const pi &a) const {
    if(first != a.first) return first > a.first;
    return true;
  }
};


template< typename key_t, size_t V >
struct SplayTree {

  const key_t e;

  SplayTree(const key_t &e) : pool(), e(e) {}

  struct Node {
    Node *l, *r, *p;
    key_t key, sum;

    Node() = default;

    Node(const key_t &k) : key(k), sum(k), l(nullptr), r(nullptr), p(nullptr) {}
  };

  ArrayPool< Node, V > pool;


  void rotr(Node *t) {
    auto *x = t->p, *y = x->p;
    if((x->l = t->r)) t->r->p = x;
    t->r = x, x->p = t;
    update(x), update(t);
    if((t->p = y)) {
      if(y->l == x) y->l = t;
      if(y->r == x) y->r = t;
      update(y);
    }
  }

  void rotl(Node *t) {
    auto *x = t->p, *y = x->p;
    if((x->r = t->l)) t->l->p = x;
    t->l = x, x->p = t;
    update(x), update(t);
    if((t->p = y)) {
      if(y->l == x) y->l = t;
      if(y->r == x) y->r = t;
      update(y);
    }
  }

  inline key_t sum(const Node *t) const {
    return t ? t->sum : e;
  }

  void update(Node *t) {
    t->sum = max({sum(t->l), t->key, sum(t->r)});
  }

  Node *get_left(Node *t) const {
    while(t->l) t = t->l;
    return t;
  }

  Node *get_right(Node *t) const {
    while(t->r) t = t->r;
    return t;
  }

  inline Node *alloc(const key_t &v) {
    return &(*pool.alloc() = Node(v));
  }

  void splay(Node *t) {
    while(t->p) {
      auto *q = t->p;
      if(!q->p) {
        if(q->l == t) rotr(t);
        else rotl(t);
      } else {
        auto *r = q->p;
        if(r->l == q) {
          if(q->l == t) rotr(q), rotr(t);
          else rotl(t), rotr(t);
        } else {
          if(q->r == t) rotl(q), rotl(t);
          else rotr(t), rotl(t);
        }
      }
    }
  }

  Node *push_back(Node *t, const key_t &v) {
    if(!t) {
      t = alloc(v);
      return t;
    } else {
      Node *cur = get_right(t), *z = alloc(v);
      z->p = cur;
      cur->r = z;
      update(cur);
      splay(z);
      return z;
    }
  }

  Node *erase(Node *t) {
    splay(t);
    Node *x = t->l, *y = t->r;
    pool.free(t);
    if(!x) {
      t = y;
      if(t) t->p = nullptr;
    } else if(!y) {
      t = x;
      t->p = nullptr;
    } else {
      x->p = nullptr;
      t = get_right(x);
      splay(t);
      t->r = y;
      y->p = t;
      update(t);
    }
    return t;
  }
};


template< typename SUM, typename KEY, size_t V >
struct LinkCutTreeSubtree {

  struct Node {
    Node *l, *r, *p;

    typename SplayTree< pi, V >::Node *light, *belong;
    KEY key;
    SUM sum;

    bool rev;
    //int sz;

    Node() = default;

    bool is_root() const {
      return !p || (p->l != this && p->r != this);
    }

    Node(const KEY &key, const SUM &sum) :
        key(key), sum(sum), rev(false), belong(nullptr),
        l(nullptr), r(nullptr), p(nullptr), light(nullptr) {}
  };

  using ST = SplayTree< pi, V >;

  ST st;
  const SUM ident;
  ArrayPool< Node, V > pool;

  LinkCutTreeSubtree(const SUM &ident) : ident(ident), st(pi(-infll, -1)), pool() {}

  Node *alloc(const KEY &key) {
    auto ret = &(*pool.alloc() = Node(key, ident));
    update(ret);
    return ret;
  }

  Node *set_key(Node *t, const KEY &key) {
    expose(t);
    t->key = key;
    update(t);
    return t;
  }

  void toggle(Node *t) {
    swap(t->l, t->r);
    t->sum.toggle();
    t->rev ^= true;
  }

  void push(Node *t) {
    if(t->rev) {
      if(t->l) toggle(t->l);
      if(t->r) toggle(t->r);
      t->rev = false;
    }
  }


  void update(Node *t) {
    t->sum.merge(t->key, t->l ? t->l->sum : ident, t->r ? t->r->sum : ident, st.sum(t->light));
  }

  void rotr(Node *t) {
    auto *x = t->p, *y = x->p;
    if((x->l = t->r)) t->r->p = x;
    t->r = x, x->p = t;
    update(x), update(t);
    if((t->p = y)) {
      if(y->l == x) y->l = t;
      if(y->r == x) y->r = t;
      update(y);
    }
  }

  void rotl(Node *t) {
    auto *x = t->p, *y = x->p;
    if((x->r = t->l)) t->l->p = x;
    t->l = x, x->p = t;
    update(x), update(t);
    if((t->p = y)) {
      if(y->l == x) y->l = t;
      if(y->r == x) y->r = t;
      update(y);
    }
  }


  void splay(Node *t) {
    push(t);

    Node *rot = t;
    while(!rot->is_root()) rot = rot->p;
    t->belong = rot->belong;
    if(t != rot) rot->belong = nullptr;

    while(!t->is_root()) {
      auto *q = t->p;
      if(q->is_root()) {
        push(q), push(t);
        if(q->l == t) rotr(t);
        else rotl(t);
      } else {
        auto *r = q->p;
        push(r), push(q), push(t);
        if(r->l == q) {
          if(q->l == t) rotr(q), rotr(t);
          else rotl(t), rotr(t);
        } else {
          if(q->r == t) rotl(q), rotl(t);
          else rotr(t), rotl(t);
        }
      }
    }

  }


  Node *expose(Node *t) {
    Node *rp = nullptr;
    for(auto *cur = t; cur; cur = cur->p) {
      splay(cur);
      if(cur->r) {
        cur->light = st.push_back(cur->light, cur->r->sum.c_max);
        cur->r->belong = cur->light;
        cur->sum.add(cur->r->sum);
      }
      cur->r = rp;
      if(cur->r) {
        cur->light = st.erase(cur->r->belong);
        cur->sum.erase(cur->r->sum);
      }
      update(cur);
      rp = cur;
    }
    splay(t);
    return rp;
  }

  void link(Node *child, Node *parent) {
    expose(child);
    expose(parent);
    child->p = parent;
    parent->r = child;
    update(parent);
  }

  void cut(Node *child) {
    expose(child);
    auto *parent = child->l;
    child->l = nullptr;
    parent->p = nullptr;
    update(child);
  }

  void evert(Node *t) {
    expose(t);
    toggle(t);
    push(t);
  }

  Node *lca(Node *u, Node *v) {
    if(get_root(u) != get_root(v)) return nullptr;
    expose(u);
    return expose(v);
  }


  Node *get_kth(Node *x, int k) {
    expose(x);
    while(x) {
      push(x);
      if(x->r && x->r->sz > k) {
        x = x->r;
      } else {
        if(x->r) k -= x->r->sz;
        if(k == 0) return x;
        k -= 1;
        x = x->l;
      }
    }
    return nullptr;
  }

  Node *get_root(Node *x) {
    expose(x);
    while(x->l) {
      push(x);
      x = x->l;
    }
    return x;
  }
};


struct Scanner {
  FILE *fp = nullptr;
  char line[(1 << 15) + 1];
  size_t st = 0, ed = 0;

  void reread() {
    memmove(line, line + st, ed - st);
    ed -= st;
    st = 0;
    ed += fread(line + ed, 1, (1 << 15) - ed, fp);
    line[ed] = '\0';
  }

  bool succ() {
    while(true) {
      if(st == ed) {
        reread();
        if(st == ed) return false;
      }
      while(st != ed && isspace(line[st])) st++;
      if(st != ed) break;
    }
    if(ed - st <= 50) reread();
    return true;
  }

  template< class T, enable_if_t< is_same< T, string >::value, int > = 0 >
  bool read_single(T &ref) {
    if(!succ()) return false;
    while(true) {
      size_t sz = 0;
      while(st + sz < ed && !isspace(line[st + sz])) sz++;
      ref.append(line + st, sz);
      st += sz;
      if(!sz || st != ed) break;
      reread();
    }
    return true;
  }

  template< class T, enable_if_t< is_integral< T >::value, int > = 0 >
  bool read_single(T &ref) {
    if(!succ()) return false;
    bool neg = false;
    if(line[st] == '-') {
      neg = true;
      st++;
    }
    ref = T(0);
    while(isdigit(line[st])) {
      ref = 10 * ref + (line[st++] - '0');
    }
    if(neg) ref = -ref;
    return true;
  }

  template< class T >
  bool read_single(vector< T > &ref) {
    for(auto &d : ref) {
      if(!read_single(d)) return false;
    }
    return true;
  }

  void read() {}

  template< class H, class... T >
  void read(H &h, T &... t) {
    bool f = read_single(h);
    assert(f);
    read(t...);
  }

  Scanner(FILE *_fp) : fp(_fp) {}
};

struct Printer {
public:
  template< bool F = false >
  void write() {}

  template< bool F = false, class H, class... T >
  void write(const H &h, const T &... t) {
    if(F) write_single(' ');
    write_single(h);
    write< true >(t...);
  }

  template< class... T >
  void writeln(const T &... t) {
    write(t...);
    write_single('\n');
  }

  Printer(FILE *_fp) : fp(_fp) {}

  ~Printer() { flush(); }

private:
  static constexpr size_t SIZE = 1 << 15;
  FILE *fp;
  char line[SIZE], small[50];
  size_t pos = 0;

  void flush() {
    fwrite(line, 1, pos, fp);
    pos = 0;
  }

  void write_single(const char &val) {
    if(pos == SIZE) flush();
    line[pos++] = val;
  }

  template< class T, enable_if_t< is_integral< T >::value, int > = 0 >
  void write_single(T val) {
    if(pos > (1 << 15) - 50) flush();
    if(val == 0) {
      write_single('0');
      return;
    }
    if(val < 0) {
      write_single('-');
      val = -val;  // todo min
    }
    size_t len = 0;
    while(val) {
      small[len++] = char('0' + (val % 10));
      val /= 10;
    }
    reverse(small, small + len);
    memcpy(line + pos, small, len);
    pos += len;
  }

  void write_single(const string &s) {
    for(char c : s) write_single(c);
  }

  void write_single(const char *s) {
    size_t len = strlen(s);
    for(size_t i = 0; i < len; i++) write_single(s[i]);
  }

  template< class T >
  void write_single(const vector< T > &val) {
    auto n = val.size();
    for(size_t i = 0; i < n; i++) {
      if(i) write_single(' ');
      write_single(val[i]);
    }
  }
};


// これがおれたちの動的木
// 動的木の時代の到来


struct Farthest {
  pi c_max, p_max;
  int64 length;

  Farthest() : c_max(pi(-infll, -1)), p_max(pi(-infll, -1)), length(0) {}

  void merge(int64 key, const Farthest &parent, const Farthest &child, const pi &t) {
    p_max = child.p_max;
    c_max = parent.c_max;
    if(key < 0) {
      chmax(p_max, pi(child.length, -key));
      chmax(c_max, pi(parent.length, -key));
      key = 0;
    }
    length = parent.length + key + child.length;
    chmax(p_max, pi(child.length + key + t.first, t.second));
    chmax(c_max, pi(parent.length + key + t.first, t.second));
    chmax(p_max, pi(child.length + key + parent.p_max.first, parent.p_max.second));
    chmax(c_max, pi(parent.length + key + child.c_max.first, child.c_max.second));
  }

  void toggle() {
    swap(c_max, p_max);
  }

  void add(const Farthest &child) {
  }

  void erase(const Farthest &child) {
  }
} e;

using LCT = LinkCutTreeSubtree< Farthest, int64, 600000 >;
LCT lct(e);
array< LCT::Node *, 200000 > ev, ee, getter;

template< typename T >
struct edge {
  int src, to;
  T cost;

  edge(int to, T cost) : src(-1), to(to), cost(cost) {}

  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

  edge &operator=(const int &x) {
    to = x;
    return *this;
  }

  operator int() const { return to; }
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedGraph = vector< Edges< T > >;
using UnWeightedGraph = vector< vector< int > >;
template< typename T >
using Matrix = vector< vector< T > >;

int uku[200000];

int main() {
  Scanner in(stdin);
  Printer out(stdout);

  int N;
  in.read(N);

  for(int i = 0; i < N; i++) {
    ev[i] = lct.alloc(0);
  }

  for(int i = 0; i < N; i++) {
    getter[i] = lct.alloc(-(i + 1));
    lct.link(getter[i], ev[i]);
  }
  vector< int > A(N), B(N);
  WeightedGraph< int > g(N);
  for(int i = 1; i < N; i++) {
    int a, b, c;
    in.read(a, b, c);
    --a, --b;
    A[i] = a, B[i] = b;
    g[a].emplace_back(b, i);
    g[b].emplace_back(a, i);
    ee[i] = lct.alloc(c);
  }
  queue< int > que;
  que.emplace(0);
  vector< int > used(N);
  used[0] = true;
  while(!que.empty()) {
    int idx = que.front();
    que.pop();
    for(auto &to : g[idx]) {
      if(used[to]) continue;
      used[to] = true;
      que.emplace(to);
      lct.link(ev[to], ee[to.cost]);
      lct.link(ee[to.cost], ev[idx]);
    }
  }

  int Q;
  in.read(Q);
  int pre = 0;
  // えっ普通に戻してsplayすればいいのかしょうもね～～

  for(int i = 0; i < Q; i++) {
    int t, x;
    in.read(t, x);
    if(t == 1) {
      --x;
      pre = x;
    } else if(t == 2) {
      lct.evert(ee[x]);
      lct.cut(ev[A[x]]);
      lct.cut(ev[B[x]]);
    } else {
      lct.evert(ev[B[x]]);
      lct.link(ev[B[x]], ee[x]);
      lct.link(ee[x], ev[A[x]]);
    }
    lct.evert(ev[pre]);

    int64 far = ev[pre]->sum.c_max.first;
    if(far == 0) {
      out.write(1);
      out.write(" ");
      out.writeln(ev[pre]->sum.c_max.second);
      continue;
    }

    int ptr = 0;
    while(far == ev[pre]->sum.c_max.first) {
      uku[ptr++] = ev[pre]->sum.c_max.second;
      lct.cut(getter[uku[ptr - 1] - 1]);
      lct.evert(ev[pre]);
    }
    sort(uku, uku + ptr);
    out.write(ptr);
    for(int k = 0; k < ptr; k++) {
      out.write(" ");
      out.write(uku[k]);
    }
    out.writeln();

    for(int k = 0; k < ptr; k++) {
      const int &p = uku[k];
      lct.link(getter[p - 1], ev[p - 1]);
    }

  }
}
accuracy: 1
time_ms: 1450
memory_kb: 122488
final_rank: 8

code_snippet: #include <bits/stdc++.h>

using namespace std;

using int64 = long long;
const int mod = 998244353;

const int64 infll = (1LL << 60) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}


template< class T, size_t V >
struct ArrayPool {
  array< T, V > pool;
  array< T *, V > stock;
  int ptr;

  ArrayPool() { clear(); }

  inline T *alloc() {
    return stock[--ptr];
  }

  inline void free(T *t) {
    stock[ptr++] = t;
  }

  void clear() {
    ptr = (int) pool.size();
    for(int i = 0; i < pool.size(); i++) stock[i] = &pool[i];
  }
};


struct pi {
  int64 first;
  int second;

  pi(const int64 &first, const int &second) : first(first), second(second) {}

  pi() = default;

  bool operator<(const pi &a) const {
    if(first != a.first) return first < a.first;
    return true;
  }

  bool operator>(const pi &a) const {
    if(first != a.first) return first > a.first;
    return true;
  }
};


template< typename key_t, size_t V >
struct SplayTree {

  const key_t e;

  SplayTree(const key_t &e) : pool(), e(e) {}

  struct Node {
    Node *l, *r, *p;
    key_t key, sum;

    Node() = default;

    Node(const key_t &k) : key(k), sum(k), l(nullptr), r(nullptr), p(nullptr) {}
  };

  ArrayPool< Node, V > pool;


  void rotr(Node *t) {
    auto *x = t->p, *y = x->p;
    if((x->l = t->r)) t->r->p = x;
    t->r = x, x->p = t;
    update(x), update(t);
    if((t->p = y)) {
      if(y->l == x) y->l = t;
      if(y->r == x) y->r = t;
      update(y);
    }
  }

  void rotl(Node *t) {
    auto *x = t->p, *y = x->p;
    if((x->r = t->l)) t->l->p = x;
    t->l = x, x->p = t;
    update(x), update(t);
    if((t->p = y)) {
      if(y->l == x) y->l = t;
      if(y->r == x) y->r = t;
      update(y);
    }
  }

  inline key_t sum(const Node *t) const {
    return t ? t->sum : e;
  }

  void update(Node *t) {
    t->sum = max({sum(t->l), t->key, sum(t->r)});
  }

  Node *get_left(Node *t) const {
    while(t->l) t = t->l;
    return t;
  }

  Node *get_right(Node *t) const {
    while(t->r) t = t->r;
    return t;
  }

  inline Node *alloc(const key_t &v) {
    return &(*pool.alloc() = Node(v));
  }

  void splay(Node *t) {
    while(t->p) {
      auto *q = t->p;
      if(!q->p) {
        if(q->l == t) rotr(t);
        else rotl(t);
      } else {
        auto *r = q->p;
        if(r->l == q) {
          if(q->l == t) rotr(q), rotr(t);
          else rotl(t), rotr(t);
        } else {
          if(q->r == t) rotl(q), rotl(t);
          else rotr(t), rotl(t);
        }
      }
    }
  }

  Node *push_back(Node *t, const key_t &v) {
    if(!t) {
      t = alloc(v);
      return t;
    } else {
      Node *cur = get_right(t), *z = alloc(v);
      z->p = cur;
      cur->r = z;
      update(cur);
      splay(z);
      return z;
    }
  }

  Node *erase(Node *t) {
    splay(t);
    Node *x = t->l, *y = t->r;
    pool.free(t);
    if(!x) {
      t = y;
      if(t) t->p = nullptr;
    } else if(!y) {
      t = x;
      t->p = nullptr;
    } else {
      x->p = nullptr;
      t = get_right(x);
      splay(t);
      t->r = y;
      y->p = t;
      update(t);
    }
    return t;
  }
};


template< typename SUM, typename KEY, size_t V >
struct LinkCutTreeSubtree {

  struct Node {
    Node *l, *r, *p;

    typename SplayTree< pi, V >::Node *light, *belong;
    KEY key;
    SUM sum;

    bool rev;
    //int sz;

    Node() = default;

    bool is_root() const {
      return !p || (p->l != this && p->r != this);
    }

    Node(const KEY &key, const SUM &sum) :
        key(key), sum(sum), rev(false), belong(nullptr),
        l(nullptr), r(nullptr), p(nullptr), light(nullptr) {}
  };

  using ST = SplayTree< pi, V >;

  ST st;
  const SUM ident;
  ArrayPool< Node, V > pool;

  LinkCutTreeSubtree(const SUM &ident) : ident(ident), st(pi(-infll, -1)), pool() {}

  Node *alloc(const KEY &key) {
    auto ret = &(*pool.alloc() = Node(key, ident));
    update(ret);
    return ret;
  }

  Node *set_key(Node *t, const KEY &key) {
    expose(t);
    t->key = key;
    update(t);
    return t;
  }

  void toggle(Node *t) {
    swap(t->l, t->r);
    t->sum.toggle();
    t->rev ^= true;
  }

  void push(Node *t) {
    if(t->rev) {
      if(t->l) toggle(t->l);
      if(t->r) toggle(t->r);
      t->rev = false;
    }
  }


  void update(Node *t) {
    t->sum.merge(t->key, t->l ? t->l->sum : ident, t->r ? t->r->sum : ident, st.sum(t->light));
  }

  void rotr(Node *t) {
    auto *x = t->p, *y = x->p;
    if((x->l = t->r)) t->r->p = x;
    t->r = x, x->p = t;
    update(x), update(t);
    if((t->p = y)) {
      if(y->l == x) y->l = t;
      if(y->r == x) y->r = t;
      update(y);
    }
  }

  void rotl(Node *t) {
    auto *x = t->p, *y = x->p;
    if((x->r = t->l)) t->l->p = x;
    t->l = x, x->p = t;
    update(x), update(t);
    if((t->p = y)) {
      if(y->l == x) y->l = t;
      if(y->r == x) y->r = t;
      update(y);
    }
  }


  void splay(Node *t) {
    push(t);

    Node *rot = t;
    while(!rot->is_root()) rot = rot->p;
    t->belong = rot->belong;
    if(t != rot) rot->belong = nullptr;

    while(!t->is_root()) {
      auto *q = t->p;
      if(q->is_root()) {
        push(q), push(t);
        if(q->l == t) rotr(t);
        else rotl(t);
      } else {
        auto *r = q->p;
        push(r), push(q), push(t);
        if(r->l == q) {
          if(q->l == t) rotr(q), rotr(t);
          else rotl(t), rotr(t);
        } else {
          if(q->r == t) rotl(q), rotl(t);
          else rotr(t), rotl(t);
        }
      }
    }

  }


  Node *expose(Node *t) {
    Node *rp = nullptr;
    for(auto *cur = t; cur; cur = cur->p) {
      splay(cur);
      if(cur->r) {
        cur->light = st.push_back(cur->light, cur->r->sum.c_max);
        cur->r->belong = cur->light;
        cur->sum.add(cur->r->sum);
      }
      cur->r = rp;
      if(cur->r) {
        cur->light = st.erase(cur->r->belong);
        cur->sum.erase(cur->r->sum);
      }
      update(cur);
      rp = cur;
    }
    splay(t);
    return rp;
  }

  void link(Node *child, Node *parent) {
    expose(child);
    expose(parent);
    child->p = parent;
    parent->r = child;
    update(parent);
  }

  void cut(Node *child) {
    expose(child);
    auto *parent = child->l;
    child->l = nullptr;
    parent->p = nullptr;
    update(child);
  }

  void evert(Node *t) {
    expose(t);
    toggle(t);
    push(t);
  }

  Node *lca(Node *u, Node *v) {
    if(get_root(u) != get_root(v)) return nullptr;
    expose(u);
    return expose(v);
  }


  Node *get_kth(Node *x, int k) {
    expose(x);
    while(x) {
      push(x);
      if(x->r && x->r->sz > k) {
        x = x->r;
      } else {
        if(x->r) k -= x->r->sz;
        if(k == 0) return x;
        k -= 1;
        x = x->l;
      }
    }
    return nullptr;
  }

  Node *get_root(Node *x) {
    expose(x);
    while(x->l) {
      push(x);
      x = x->l;
    }
    return x;
  }
};


struct Scanner {
  FILE *fp = nullptr;
  char line[(1 << 15) + 1];
  size_t st = 0, ed = 0;

  void reread() {
    memmove(line, line + st, ed - st);
    ed -= st;
    st = 0;
    ed += fread(line + ed, 1, (1 << 15) - ed, fp);
    line[ed] = '\0';
  }

  bool succ() {
    while(true) {
      if(st == ed) {
        reread();
        if(st == ed) return false;
      }
      while(st != ed && isspace(line[st])) st++;
      if(st != ed) break;
    }
    if(ed - st <= 50) reread();
    return true;
  }

  template< class T, enable_if_t< is_same< T, string >::value, int > = 0 >
  bool read_single(T &ref) {
    if(!succ()) return false;
    while(true) {
      size_t sz = 0;
      while(st + sz < ed && !isspace(line[st + sz])) sz++;
      ref.append(line + st, sz);
      st += sz;
      if(!sz || st != ed) break;
      reread();
    }
    return true;
  }

  template< class T, enable_if_t< is_integral< T >::value, int > = 0 >
  bool read_single(T &ref) {
    if(!succ()) return false;
    bool neg = false;
    if(line[st] == '-') {
      neg = true;
      st++;
    }
    ref = T(0);
    while(isdigit(line[st])) {
      ref = 10 * ref + (line[st++] - '0');
    }
    if(neg) ref = -ref;
    return true;
  }

  template< class T >
  bool read_single(vector< T > &ref) {
    for(auto &d : ref) {
      if(!read_single(d)) return false;
    }
    return true;
  }

  void read() {}

  template< class H, class... T >
  void read(H &h, T &... t) {
    bool f = read_single(h);
    assert(f);
    read(t...);
  }

  Scanner(FILE *_fp) : fp(_fp) {}
};

struct Printer {
public:
  template< bool F = false >
  void write() {}

  template< bool F = false, class H, class... T >
  void write(const H &h, const T &... t) {
    if(F) write_single(' ');
    write_single(h);
    write< true >(t...);
  }

  template< class... T >
  void writeln(const T &... t) {
    write(t...);
    write_single('\n');
  }

  Printer(FILE *_fp) : fp(_fp) {}

  ~Printer() { flush(); }

private:
  static constexpr size_t SIZE = 1 << 15;
  FILE *fp;
  char line[SIZE], small[50];
  size_t pos = 0;

  void flush() {
    fwrite(line, 1, pos, fp);
    pos = 0;
  }

  void write_single(const char &val) {
    if(pos == SIZE) flush();
    line[pos++] = val;
  }

  template< class T, enable_if_t< is_integral< T >::value, int > = 0 >
  void write_single(T val) {
    if(pos > (1 << 15) - 50) flush();
    if(val == 0) {
      write_single('0');
      return;
    }
    if(val < 0) {
      write_single('-');
      val = -val;  // todo min
    }
    size_t len = 0;
    while(val) {
      small[len++] = char('0' + (val % 10));
      val /= 10;
    }
    reverse(small, small + len);
    memcpy(line + pos, small, len);
    pos += len;
  }

  void write_single(const string &s) {
    for(char c : s) write_single(c);
  }

  void write_single(const char *s) {
    size_t len = strlen(s);
    for(size_t i = 0; i < len; i++) write_single(s[i]);
  }

  template< class T >
  void write_single(const vector< T > &val) {
    auto n = val.size();
    for(size_t i = 0; i < n; i++) {
      if(i) write_single(' ');
      write_single(val[i]);
    }
  }
};


// これがおれたちの動的木
// 動的木の時代の到来


struct Farthest {
  pi c_max, p_max;
  int64 length;

  Farthest() : c_max(pi(-infll, -1)), p_max(pi(-infll, -1)), length(0) {}

  void merge(int64 key, const Farthest &parent, const Farthest &child, const pi &t) {
    p_max = child.p_max;
    c_max = parent.c_max;
    if(key < 0) {
      chmax(p_max, pi(child.length, -key));
      chmax(c_max, pi(parent.length, -key));
      key = 0;
    }
    length = parent.length + key + child.length;
    chmax(p_max, pi(child.length + key + t.first, t.second));
    chmax(c_max, pi(parent.length + key + t.first, t.second));
    chmax(p_max, pi(child.length + key + parent.p_max.first, parent.p_max.second));
    chmax(c_max, pi(parent.length + key + child.c_max.first, child.c_max.second));
  }

  void toggle() {
    swap(c_max, p_max);
  }

  void add(const Farthest &child) {
  }

  void erase(const Farthest &child) {
  }
} e;

using LCT = LinkCutTreeSubtree< Farthest, int64, 600000 >;
LCT lct(e);
array< LCT::Node *, 200000 > ev, ee, getter;

template< typename T >
struct edge {
  int src, to;
  T cost;

  edge(int to, T cost) : src(-1), to(to), cost(cost) {}

  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

  edge &operator=(const int &x) {
    to = x;
    return *this;
  }

  operator int() const { return to; }
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedGraph = vector< Edges< T > >;
using UnWeightedGraph = vector< vector< int > >;
template< typename T >
using Matrix = vector< vector< T > >;

int uku[200000];

int main() {
  Scanner in(stdin);
  Printer out(stdout);

  int N;
  in.read(N);

  for(int i = 0; i < N; i++) {
    ev[i] = lct.alloc(0);
  }

  for(int i = 0; i < N; i++) {
    getter[i] = lct.alloc(-(i + 1));
    lct.link(getter[i], ev[i]);
  }
  vector< int > A(N), B(N);
  WeightedGraph< int > g(N);
  for(int i = 1; i < N; i++) {
    int a, b, c;
    in.read(a, b, c);
    --a, --b;
    A[i] = a, B[i] = b;
    g[a].emplace_back(b, i);
    g[b].emplace_back(a, i);
    ee[i] = lct.alloc(c);
  }
  queue< int > que;
  que.emplace(0);
  vector< int > used(N);
  used[0] = true;
  while(!que.empty()) {
    int idx = que.front();
    que.pop();
    for(auto &to : g[idx]) {
      if(used[to]) continue;
      used[to] = true;
      que.emplace(to);
      lct.link(ev[to], ee[to.cost]);
      lct.link(ee[to.cost], ev[idx]);
    }
  }

  int Q;
  in.read(Q);
  int pre = 0;
  // えっ普通に戻してsplayすればいいのかしょうもね～～

  for(int i = 0; i < Q; i++) {
    int t, x;
    in.read(t, x);
    if(t == 1) {
      --x;
      pre = x;
    } else if(t == 2) {
      lct.evert(ee[x]);
      lct.cut(ev[A[x]]);
      lct.cut(ev[B[x]]);
    } else {
      lct.evert(ev[B[x]]);
      lct.link(ev[B[x]], ee[x]);
      lct.link(ee[x], ev[A[x]]);
    }
    lct.evert(ev[pre]);

    int64 far = ev[pre]->sum.c_max.first;
    if(far == 0) {
      out.write(1);
      out.write(" ");
      out.writeln(ev[pre]->sum.c_max.second);
      continue;
    }

    int ptr = 0;
    while(far == ev[pre]->sum.c_max.first) {
      uku[ptr++] = ev[pre]->sum.c_max.second;
      lct.cut(getter[uku[ptr - 1] - 1]);
      lct.evert(ev[pre]);
    }
    sort(uku, uku + ptr);
    out.write(ptr);
    for(int k = 0; k < ptr; k++) {
      out.write(" ");
      out.write(uku[k]);
    }
    out.writeln();

    for(int k = 0; k < ptr; k++) {
      const int &p = uku[k];
      lct.link(getter[p - 1], ev[p - 1]);
    }

  }
}
accuracy: 1
time_ms: 1460
memory_kb: 122400
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using graph = vector<vector<pil>>;

const ll INF = 1e11;

const int S_MAX = 4e5;

struct RU {
	using t1 = pli;
	using t2 = ll;
	static t1 id1() { return make_pair(-1000000000000000000LL, -1); }
	static t2 id2() { return 0; }
	static t1 op1(const t1& l, const t1& r) { return max(l, r); }
	static t1 op2(const t1& l, const t2& r) { return make_pair(l.first + r, l.second); }
	static t2 op3(const t2& l, const t2& r) { return l + r; }
};

template <typename M>
class lazy_segment_tree {
	using T1 = typename M::t1;
	using T2 = typename M::t2;
	const int h, n;
	vector<T1> data;
	vector<T2> lazy;
	void push(int node) {
		if (lazy[node] == M::id2()) return;
		if (node < n) {
			lazy[node * 2] = M::op3(lazy[node * 2], lazy[node]);
			lazy[node * 2 + 1] = M::op3(lazy[node * 2 + 1], lazy[node]);
		}
		data[node] = M::op2(data[node], lazy[node]);
		lazy[node] = M::id2();
	}
	void update(int node) {
		data[node] = M::op1(M::op2(data[node * 2], lazy[node * 2]), M::op2(data[node * 2 + 1], lazy[node * 2 + 1]));
	}
public:
	lazy_segment_tree(int n_)
		: h(ceil(log2(n_))), n(1 << h), data(n * 2, M::id1()), lazy(n * 2, M::id2()) {}
	lazy_segment_tree(int n_, T1 v1)
		: h(ceil(log2(n_))), n(1 << h), data(n * 2, v1), lazy(n * 2, M::id2()) {}
	lazy_segment_tree(const vector<T1>& data_)
		: h(ceil(log2(data_.size()))), n(1 << h), data(n * 2, M::id1()), lazy(n * 2, M::id2()) {
		init(data_);
	}
	void init() {
		for (int i = n - 1; i >= 1; i--) data[i] = M::op1(data[i * 2], data[i * 2 + 1]);
	}
	void init(const vector<T1>& data_) {
		for (int i = 0; i < (int)data_.size(); i++) data[i + n] = data_[i];
		init();
	}
	void update(int l, int r, T2 val) {
		if (l >= r) return;
		l += n, r += n - 1;
		for (int i = h; i > 0; i--) push(l >> i), push(r >> i);
		int tl = l, tr = r;
		r++;
		while (l < r) {
			if (l & 1) lazy[l] = M::op3(lazy[l], val), l++;
			if (r & 1) r--, lazy[r] = M::op3(lazy[r], val);
			l >>= 1; r >>= 1;
		}
		while (tl >>= 1, tr >>= 1, tl) {
			if (lazy[tl] == M::id2()) update(tl);
			if (lazy[tr] == M::id2()) update(tr);
		}
	}
	T1 find(int l, int r) {
		l += n, r += n - 1;
		for (int i = h; i > 0; i--) push(l >> i), push(r >> i);
		r++;
		T1 res1 = M::id1(), res2 = M::id1();
		while (l < r) {
			if (l & 1) res1 = M::op1(res1, M::op2(data[l], lazy[l])), l++;
			if (r & 1) r--, res2 = M::op1(M::op2(data[r], lazy[r]), res2);
			l >>= 1; r >>= 1;
		}
		return M::op1(res1, res2);
	}
};

const int MAX = 2e5;

int it;

int par[MAX];
int lv[MAX], rv[MAX], vs[MAX];

void dfs(int v, int prev, ll d, const graph& G, vector<pli>& dist) {
	par[v] = prev;
	vs[it] = v;
	dist[it] = make_pair(d, it);
	lv[v] = it++;
	for (auto e : G[v]) if (e.first != prev) {
		dfs(e.first, v, d + e.second, G, dist);
	}
	rv[v] = it;
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(0);
	int N;
	cin >> N;
	graph G(N);
	unordered_map<int, unordered_map<int, ll>> es;
	vector<int> a(N - 1), b(N - 1);
	for (int i = 0; i < N - 1; i++) {
		int d;
		cin >> a[i] >> b[i] >> d; --a[i], --b[i];
		G[a[i]].emplace_back(b[i], d);
		G[b[i]].emplace_back(a[i], d);
		es[a[i]][b[i]] = es[b[i]][a[i]] = d;
	}
	vector<pli> dist(N);
	it = 0;
	dfs(0, -1, 0, G, dist);
	lazy_segment_tree<RU> lst(dist);
	int pos = 0, cnt = 0;
	int Q;
	cin >> Q;
	while (Q--) {
		int com;
		cin >> com;
		if (com == 1) {
			int v;
			cin >> v; --v;
			ll cost = es[pos][v];
			if (v == par[pos]) {
				lst.update(0, lv[pos], -cost);
				lst.update(lv[pos], rv[pos], cost);
				lst.update(rv[pos], N, -cost);
			}
			else {
				lst.update(0, lv[v], cost);
				lst.update(lv[v], rv[v], -cost);
				lst.update(rv[v], N, cost);
			}
			pos = v;
		}
		else if (com == 2) {
			int id;
			cin >> id; --id;
			int u = a[id], v = b[id];
			if (lv[v] <= lv[u] && rv[u] <= rv[v]) swap(u, v);
			if (lv[pos] <= lv[u] && rv[u] <= rv[pos]) {
				lst.update(lv[v], rv[v], -INF);
			}
			else if (lv[v] <= lv[pos] && rv[pos] <= rv[v]) {
				lst.update(0, lv[v], -INF);
				lst.update(rv[v], N, -INF);
			}
			else {
				lst.update(lv[v], rv[v], -INF);
			}
		}
		else {
			int id;
			cin >> id; --id;
			int u = a[id], v = b[id];
			if (lv[v] <= lv[u] && rv[u] <= rv[v]) swap(u, v);
			if (lv[pos] <= lv[u] && rv[u] <= rv[pos]) {
				lst.update(lv[v], rv[v], INF);
			}
			else if (lv[v] <= lv[pos] && rv[pos] <= rv[v]) {
				lst.update(0, lv[v], INF);
				lst.update(rv[v], N, INF);
			}
			else {
				lst.update(lv[v], rv[v], INF);
			}
		}
		ll d = lst.find(0, N).first;
		int ub = N;
		pli tmp;
		vector<int> res;
		while ((tmp = lst.find(0, ub)).first == d) {
			int id = tmp.second;
			res.push_back(vs[id]);
			ub = id;
		}
		sort(res.begin(), res.end());
		cout << res.size();
		for (int i = 0; i < (int)res.size(); i++) {
			cout << ' ' << res[i] + 1;
		}
		cout << '\n';
		cnt += res.size();
		assert(cnt <= S_MAX);
	}
	return 0;
}
accuracy: 1
time_ms: 500
memory_kb: 88596
final_rank: 4

code_snippet: #include <bits/stdc++.h>

using namespace std;

using ll = long long;

struct StarrySkyTree{
private:
    int n;
    vector<pair<ll, int>> node;
    vector<ll> lazy;

public:
    StarrySkyTree(int sz, vector<ll> &v){
        n = 1;
        while(n < sz) n *= 2;
        node.resize(2 * n - 1);
        lazy.resize(2 * n - 1);
        for(int i = 0; i < sz; i++) node[i + n - 1] = {v[i], i};
        for(int i = n - 2; i >= 0; i--) node[i] = max(node[i * 2 + 1], node[i * 2 + 2]);
    }

    void eval(int k, int l, int r){
        if(lazy[k] != 0){
            node[k].first += lazy[k];
            if(r - l > 1){
                lazy[2 * k + 1] += lazy[k];
                lazy[2 * k + 2] += lazy[k];
            }
            lazy[k] = 0;
        }
    }

    void add(int a, int b, ll x, int k = 0, int l = 0, int r = -1){
        if(r < 0) r = n;
        eval(k, l, r);
        if(b <= l || r <= a) return;
        if(a <= l && r <= b){
            lazy[k] += x;
            eval(k, l, r);
        }else{
            add(a, b, x, 2 * k + 1, l, (l + r) / 2);
            add(a, b, x, 2 * k + 2, (l + r) / 2, r);
            node[k] = max(node[2 * k + 1], node[2 * k + 2]);
        }
    }

    pair<ll, int> getmax(int a, int b, int k = 0, int l = 0, int r = -1){
        if(r < 0) r = n;
        if(b <= l || r <= a) return {-1, -1};
        eval(k, l, r);
        if(a <= l && r <= b) return node[k];
        pair<ll, int> vl = getmax(a, b, 2 * k + 1, l, (l + r) / 2);
        pair<ll, int> vr = getmax(a, b, 2 * k + 2, (l + r) / 2, r);
        return max(vl, vr);
    }
};

int n;
vector<vector<int>> e;
vector<int> a, b;
vector<ll> d;

int idx;
vector<ll> depth;
vector<int> l, r;
vector<int> par;
vector<int> wh;

void dfs(int x, int p){
    l[x] = idx++;
    wh[l[x]] = x;
    for(auto &id:e[x]){
        if(a[id] == p) continue;
        if(a[id] != x) swap(a[id], b[id]);
        depth[idx] = depth[l[x]] + d[id];
        par[b[id]] = id;
        dfs(b[id], x);
    }
    r[x] = idx;
}

int main(){
    cin.tie(0);ios::sync_with_stdio(false);

    cin >> n;
    a = b = vector<int>(n);
    d = vector<ll>(n);
    e = vector<vector<int>>(n);
    for(int i = 0; i < n - 1; i++){
        cin >> a[i] >> b[i] >> d[i];
        a[i]--, b[i]--;
        e[a[i]].push_back(i);
        e[b[i]].push_back(i);
    }

    idx = 0;
    l = r = par = wh = vector<int>(n);
    depth = vector<ll>(n);
    dfs(0, -1);

    StarrySkyTree seg(n, depth);

    int q;
    cin >> q;
    int c, v;
    const ll inf = 3e11;
    int now = 0;
    for(int t = 0; t < q; t++){
        cin >> c >> v;
        v--;
        if(c == 1){
            if(now > 0 && a[par[now]] == v){
                seg.add(0, n, -d[par[now]]);
                seg.add(l[now], r[now], 2 * d[par[now]]);
            }else{
                seg.add(0, n, d[par[v]]);
                seg.add(l[v], r[v], -2 * d[par[v]]);
            }
            now = v;
        }else if(c == 2){
            if(l[b[v]] <= l[now] && l[now] < r[b[v]]){
                seg.add(0, n, -inf);
                seg.add(l[b[v]], r[b[v]], inf);
            }else{
                seg.add(l[b[v]], r[b[v]], -inf);
            }
        }else{
            if(l[b[v]] <= l[now] && l[now] < r[b[v]]){
                seg.add(0, n, inf);
                seg.add(l[b[v]], r[b[v]], -inf);
            }else{
                seg.add(l[b[v]], r[b[v]], inf);
            }
        }

        vector<int> ans;
        pair<int, int> p = seg.getmax(0, n);
        pair<int, int> far = p;
        while(p.first == far.first){
            ans.push_back(p.second);
            seg.add(p.second, p.second + 1, -inf);
            p = seg.getmax(0, n);
        }

        sort(ans.begin(), ans.end(), [&](int &l, int &r){
            return wh[l] < wh[r];
        });

        cout << ans.size();
        for(auto &x:ans){
            cout << " " << wh[x] + 1;
            seg.add(x, x + 1, inf);
        }
        cout << "\n";
    }
    cout << flush;

    return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 42400
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using graph = vector<vector<pil>>;

const ll INF = 1e12;

const int S_MAX = 4e5;

struct RU {
	using t1 = pli;
	using t2 = ll;
	static t1 id1() { return make_pair(-1000000000000000000LL, -1); }
	static t2 id2() { return 0; }
	static t1 op1(const t1& l, const t1& r) { return max(l, r); }
	static t1 op2(const t1& l, const t2& r) { return make_pair(l.first + r, l.second); }
	static t2 op3(const t2& l, const t2& r) { return l + r; }
};

template <typename M>
class lazy_segment_tree {
	using T1 = typename M::t1;
	using T2 = typename M::t2;
	const int h, n;
	vector<T1> data;
	vector<T2> lazy;
	void push(int node) {
		if (lazy[node] == M::id2()) return;
		if (node < n) {
			lazy[node * 2] = M::op3(lazy[node * 2], lazy[node]);
			lazy[node * 2 + 1] = M::op3(lazy[node * 2 + 1], lazy[node]);
		}
		data[node] = M::op2(data[node], lazy[node]);
		lazy[node] = M::id2();
	}
	void update(int node) {
		data[node] = M::op1(M::op2(data[node * 2], lazy[node * 2]), M::op2(data[node * 2 + 1], lazy[node * 2 + 1]));
	}
public:
	lazy_segment_tree(int n_)
		: h(ceil(log2(n_))), n(1 << h), data(n * 2, M::id1()), lazy(n * 2, M::id2()) {}
	lazy_segment_tree(int n_, T1 v1)
		: h(ceil(log2(n_))), n(1 << h), data(n * 2, v1), lazy(n * 2, M::id2()) {}
	lazy_segment_tree(const vector<T1>& data_)
		: h(ceil(log2(data_.size()))), n(1 << h), data(n * 2, M::id1()), lazy(n * 2, M::id2()) {
		init(data_);
	}
	void init() {
		for (int i = n - 1; i >= 1; i--) data[i] = M::op1(data[i * 2], data[i * 2 + 1]);
	}
	void init(const vector<T1>& data_) {
		for (int i = 0; i < (int)data_.size(); i++) data[i + n] = data_[i];
		init();
	}
	void update(int l, int r, T2 val) {
		if (l >= r) return;
		l += n, r += n - 1;
		for (int i = h; i > 0; i--) push(l >> i), push(r >> i);
		int tl = l, tr = r;
		r++;
		while (l < r) {
			if (l & 1) lazy[l] = M::op3(lazy[l], val), l++;
			if (r & 1) r--, lazy[r] = M::op3(lazy[r], val);
			l >>= 1; r >>= 1;
		}
		while (tl >>= 1, tr >>= 1, tl) {
			if (lazy[tl] == M::id2()) update(tl);
			if (lazy[tr] == M::id2()) update(tr);
		}
	}
	T1 find(int l, int r) {
		l += n, r += n - 1;
		for (int i = h; i > 0; i--) push(l >> i), push(r >> i);
		r++;
		T1 res1 = M::id1(), res2 = M::id1();
		while (l < r) {
			if (l & 1) res1 = M::op1(res1, M::op2(data[l], lazy[l])), l++;
			if (r & 1) r--, res2 = M::op1(M::op2(data[r], lazy[r]), res2);
			l >>= 1; r >>= 1;
		}
		return M::op1(res1, res2);
	}
};

const int MAX = 2e5;

int it;

int par[MAX];
int lv[MAX], rv[MAX], vs[MAX];

void dfs(int v, int prev, ll d, const graph& G, vector<pli>& dist) {
	par[v] = prev;
	vs[it] = v;
	dist[it] = make_pair(d, it);
	lv[v] = it++;
	for (auto e : G[v]) if (e.first != prev) {
		dfs(e.first, v, d + e.second, G, dist);
	}
	rv[v] = it;
}

int main()
{
	int N;
	cin >> N;
	graph G(N);
	unordered_map<int, unordered_map<int, ll>> es;
	vector<int> a(N - 1), b(N - 1);
	for (int i = 0; i < N - 1; i++) {
		int d;
		cin >> a[i] >> b[i] >> d; --a[i], --b[i];
		G[a[i]].emplace_back(b[i], d);
		G[b[i]].emplace_back(a[i], d);
		es[a[i]][b[i]] = es[b[i]][a[i]] = d;
	}
	vector<pli> dist(N);
	it = 0;
	dfs(0, -1, 0, G, dist);
	lazy_segment_tree<RU> lst(dist);
	int pos = 0, cnt = 0;
	int Q;
	cin >> Q;
	while (Q--) {
		int com;
		cin >> com;
		if (com == 1) {
			int v;
			cin >> v; --v;
			ll cost = es[pos][v];
			if (v == par[pos]) {
				lst.update(0, lv[pos], -cost);
				lst.update(lv[pos], rv[pos], cost);
				lst.update(rv[pos], N, -cost);
			}
			else {
				lst.update(0, lv[v], cost);
				lst.update(lv[v], rv[v], -cost);
				lst.update(rv[v], N, cost);
			}
			pos = v;
		}
		else if (com == 2) {
			int id;
			cin >> id; --id;
			int u = a[id], v = b[id];
			if (lv[v] <= lv[u] && rv[u] <= rv[v]) swap(u, v);
			if (lv[pos] <= lv[u] && rv[u] <= rv[pos]) {
				lst.update(lv[v], rv[v], -INF);
			}
			else if (lv[v] <= lv[pos] && rv[pos] <= rv[v]) {
				lst.update(0, lv[v], -INF);
				lst.update(rv[v], N, -INF);
			}
			else {
				lst.update(lv[v], rv[v], -INF);
			}
		}
		else {
			int id;
			cin >> id; --id;
			int u = a[id], v = b[id];
			if (lv[v] <= lv[u] && rv[u] <= rv[v]) swap(u, v);
			if (lv[pos] <= lv[u] && rv[u] <= rv[pos]) {
				lst.update(lv[v], rv[v], INF);
			}
			else if (lv[v] <= lv[pos] && rv[pos] <= rv[v]) {
				lst.update(0, lv[v], INF);
				lst.update(rv[v], N, INF);
			}
			else {
				lst.update(lv[v], rv[v], INF);
			}
		}
		ll d = lst.find(0, N).first;
		int ub = N;
		pli tmp;
		vector<int> res;
		while ((tmp = lst.find(0, ub)).first == d) {
			int id = tmp.second;
			res.push_back(vs[id]);
			ub = id;
		}
		sort(res.begin(), res.end());
		cout << res.size();
		for (int i = 0; i < (int)res.size(); i++) {
			cout << ' ' << res[i] + 1;
		}
		cout << endl;
		cnt += res.size();
		assert(cnt <= S_MAX);
	}
	return 0;
}
accuracy: 1
time_ms: 850
memory_kb: 88564
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using graph = vector<vector<pil>>;

const ll INF = 1e12;

const int S_MAX = 4e5;

struct RU {
	using t1 = pli;
	using t2 = ll;
	static t1 id1() { return make_pair(-1000000000000000000LL, -1); }
	static t2 id2() { return 0; }
	static t1 op1(const t1& l, const t1& r) { return max(l, r); }
	static t1 op2(const t1& l, const t2& r) { return make_pair(l.first + r, l.second); }
	static t2 op3(const t2& l, const t2& r) { return l + r; }
};

template <typename M>
class lazy_segment_tree {
	using T1 = typename M::t1;
	using T2 = typename M::t2;
	const int h, n;
	vector<T1> data;
	vector<T2> lazy;
	void push(int node) {
		if (lazy[node] == M::id2()) return;
		if (node < n) {
			lazy[node * 2] = M::op3(lazy[node * 2], lazy[node]);
			lazy[node * 2 + 1] = M::op3(lazy[node * 2 + 1], lazy[node]);
		}
		data[node] = M::op2(data[node], lazy[node]);
		lazy[node] = M::id2();
	}
	void update(int node) {
		data[node] = M::op1(M::op2(data[node * 2], lazy[node * 2]), M::op2(data[node * 2 + 1], lazy[node * 2 + 1]));
	}
public:
	lazy_segment_tree(int n_)
		: h(ceil(log2(n_))), n(1 << h), data(n * 2, M::id1()), lazy(n * 2, M::id2()) {}
	lazy_segment_tree(int n_, T1 v1)
		: h(ceil(log2(n_))), n(1 << h), data(n * 2, v1), lazy(n * 2, M::id2()) {}
	lazy_segment_tree(const vector<T1>& data_)
		: h(ceil(log2(data_.size()))), n(1 << h), data(n * 2, M::id1()), lazy(n * 2, M::id2()) {
		init(data_);
	}
	void init() {
		for (int i = n - 1; i >= 1; i--) data[i] = M::op1(data[i * 2], data[i * 2 + 1]);
	}
	void init(const vector<T1>& data_) {
		for (int i = 0; i < (int)data_.size(); i++) data[i + n] = data_[i];
		init();
	}
	void update(int l, int r, T2 val) {
		if (l >= r) return;
		l += n, r += n - 1;
		for (int i = h; i > 0; i--) push(l >> i), push(r >> i);
		int tl = l, tr = r;
		r++;
		while (l < r) {
			if (l & 1) lazy[l] = M::op3(lazy[l], val), l++;
			if (r & 1) r--, lazy[r] = M::op3(lazy[r], val);
			l >>= 1; r >>= 1;
		}
		while (tl >>= 1, tr >>= 1, tl) {
			if (lazy[tl] == M::id2()) update(tl);
			if (lazy[tr] == M::id2()) update(tr);
		}
	}
	T1 find(int l, int r) {
		l += n, r += n - 1;
		for (int i = h; i > 0; i--) push(l >> i), push(r >> i);
		r++;
		T1 res1 = M::id1(), res2 = M::id1();
		while (l < r) {
			if (l & 1) res1 = M::op1(res1, M::op2(data[l], lazy[l])), l++;
			if (r & 1) r--, res2 = M::op1(M::op2(data[r], lazy[r]), res2);
			l >>= 1; r >>= 1;
		}
		return M::op1(res1, res2);
	}
};

const int MAX = 2e5;

int it;

int par[MAX];
int lv[MAX], rv[MAX], vs[MAX];

void dfs(int v, int prev, ll d, const graph& G, vector<pli>& dist) {
	par[v] = prev;
	vs[it] = v;
	dist[it] = make_pair(d, it);
	lv[v] = it++;
	for (auto e : G[v]) if (e.first != prev) {
		dfs(e.first, v, d + e.second, G, dist);
	}
	rv[v] = it;
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(0);
	int N;
	cin >> N;
	graph G(N);
	unordered_map<int, unordered_map<int, ll>> es;
	vector<int> a(N - 1), b(N - 1);
	for (int i = 0; i < N - 1; i++) {
		int d;
		cin >> a[i] >> b[i] >> d; --a[i], --b[i];
		G[a[i]].emplace_back(b[i], d);
		G[b[i]].emplace_back(a[i], d);
		es[a[i]][b[i]] = es[b[i]][a[i]] = d;
	}
	vector<pli> dist(N);
	it = 0;
	dfs(0, -1, 0, G, dist);
	lazy_segment_tree<RU> lst(dist);
	int pos = 0, cnt = 0;
	int Q;
	cin >> Q;
	while (Q--) {
		int com;
		cin >> com;
		if (com == 1) {
			int v;
			cin >> v; --v;
			ll cost = es[pos][v];
			if (v == par[pos]) {
				lst.update(0, lv[pos], -cost);
				lst.update(lv[pos], rv[pos], cost);
				lst.update(rv[pos], N, -cost);
			}
			else {
				lst.update(0, lv[v], cost);
				lst.update(lv[v], rv[v], -cost);
				lst.update(rv[v], N, cost);
			}
			pos = v;
		}
		else if (com == 2) {
			int id;
			cin >> id; --id;
			int u = a[id], v = b[id];
			if (lv[v] <= lv[u] && rv[u] <= rv[v]) swap(u, v);
			if (lv[pos] <= lv[u] && rv[u] <= rv[pos]) {
				lst.update(lv[v], rv[v], -INF);
			}
			else if (lv[v] <= lv[pos] && rv[pos] <= rv[v]) {
				lst.update(0, lv[v], -INF);
				lst.update(rv[v], N, -INF);
			}
			else {
				lst.update(lv[v], rv[v], -INF);
			}
		}
		else {
			int id;
			cin >> id; --id;
			int u = a[id], v = b[id];
			if (lv[v] <= lv[u] && rv[u] <= rv[v]) swap(u, v);
			if (lv[pos] <= lv[u] && rv[u] <= rv[pos]) {
				lst.update(lv[v], rv[v], INF);
			}
			else if (lv[v] <= lv[pos] && rv[pos] <= rv[v]) {
				lst.update(0, lv[v], INF);
				lst.update(rv[v], N, INF);
			}
			else {
				lst.update(lv[v], rv[v], INF);
			}
		}
		ll d = lst.find(0, N).first;
		int ub = N;
		pli tmp;
		vector<int> res;
		while ((tmp = lst.find(0, ub)).first == d) {
			int id = tmp.second;
			res.push_back(vs[id]);
			ub = id;
		}
		sort(res.begin(), res.end());
		cout << res.size();
		for (int i = 0; i < (int)res.size(); i++) {
			cout << ' ' << res[i] + 1;
		}
		cout << '\n';
		cnt += res.size();
		assert(cnt <= S_MAX);
	}
	return 0;
}
accuracy: 1
time_ms: 510
memory_kb: 88628
final_rank: 5