description: You have an array of integers (initially empty).
  
  You have to perform q queries. Each query is of one of two types: 
  
    * "1 x" — add the element x to the end of the array; 
    * "2 x y" — replace all occurrences of x in the array with y. 
  
  
  
  Find the resulting array after performing all the queries.
  
  Input
  
  The first line contains a single integer q (1 ≤ q ≤ 5 ⋅ 10^5) — the number of queries.
  
  Next q lines contain queries (one per line). Each query is of one of two types: 
  
    * "1 x" (1 ≤ x ≤ 5 ⋅ 10^5); 
    * "2 x y" (1 ≤ x, y ≤ 5 ⋅ 10^5). 
  
  
  
  It's guaranteed that there is at least one query of the first type.
  
  Output
  
  In a single line, print k integers — the resulting array after performing all the queries, where k is the number of queries of the first type.
  
  Examples
  
  Input
  
  
  7
  1 3
  1 1
  2 1 2
  1 2
  1 1
  1 2
  2 1 3
  
  
  Output
  
  
  3 2 2 3 2 
  
  Input
  
  
  4
  1 1
  1 2
  1 1
  2 2 2
  
  
  Output
  
  
  1 2 1 
  
  Input
  
  
  8
  2 1 4
  1 1
  1 4
  1 2
  2 2 4
  2 4 3
  1 2
  2 2 7
  
  
  Output
  
  
  1 3 3 7 
  
  Note
  
  In the first example, the array changes as follows:
  
  [] → [3] → [3, 1] → [3, 2] → [3, 2, 2] → [3, 2, 2, 1] → [3, 2, 2, 1, 2] → [3, 2, 2, 3, 2].
  
  In the second example, the array changes as follows:
  
  [] → [1] → [1, 2] → [1, 2, 1] → [1, 2, 1].
  
  In the third example, the array changes as follows:
  
  [] → [] → [1] → [1, 4] → [1, 4, 2] → [1, 4, 4] → [1, 3, 3] → [1, 3, 3, 2] → [1, 3, 3, 7].
solution: #include <bits/stdc++.h>
  using namespace std;
  FILE* in = stdin;
  FILE* out = stdout;
  const int MAX = 500005;
  struct Link {
    int index, prev;
    Link(int index_ = 0, int prev_ = -1) : index(index_), prev(prev_){};
  };
  int n;
  Link a[MAX];
  int start[MAX], last[MAX];
  void addLink(int value, int idx) {
    a[idx] = Link(idx, start[value]);
    start[value] = idx;
    if (last[value] == -1) last[value] = idx;
  }
  void reLink(int oldValue, int newValue) {
    if (oldValue == newValue) return;
    if (start[oldValue] == -1) return;
    if (start[newValue] == -1) {
      start[newValue] = start[oldValue], start[oldValue] = -1;
      last[newValue] = last[oldValue], last[oldValue] = -1;
      return;
    }
    a[last[oldValue]].prev = start[newValue];
    start[newValue] = start[oldValue];
    start[oldValue] = -1, last[oldValue] = -1;
  }
  int main(void) {
    memset(start, -1, sizeof(start));
    memset(last, -1, sizeof(last));
    int numQueries;
    fscanf(in, "%d", &numQueries);
    int nextIdx = 0;
    for (int i = 0; i < numQueries; i++) {
      int type;
      fscanf(in, "%d", &type);
      if (type == 1) {
        int value;
        fscanf(in, "%d", &value);
        addLink(value, nextIdx++);
      } else {
        int oldValue, newValue;
        fscanf(in, "%d %d", &oldValue, &newValue);
        reLink(oldValue, newValue);
      }
    }
    vector<int> ans(nextIdx);
    for (int value = 0; value < MAX; value++) {
      for (int idx = start[value]; idx != -1; idx = a[idx].prev) {
        ans[a[idx].index] = value;
      }
    }
    for (int i = 0; i < (int)ans.size(); i++)
      fprintf(out, "%d%c", ans[i], i + 1 == (int)ans.size() ? '\n' : ' ');
    return 0;
  }
  