Problem:
Score : 400 points

Problem Statement

You have a sequence A composed of N positive integers: A_{1}, A_{2}, \cdots, A_{N}.

You will now successively do the following Q operations:

In the i-th operation, you replace every element whose value is B_{i} with C_{i}.

For each i (1 \leq i \leq Q), find S_{i}: the sum of all elements in A just after the i-th operation.

Constraints

All values in input are integers.

1 \leq N, Q, A_{i}, B_{i}, C_{i} \leq 10^{5}

B_{i} \neq C_{i}

Input

Input is given from Standard Input in the following format:

N
A_{1} A_{2} \cdots A_{N}
Q
B_{1} C_{1}
B_{2} C_{2}
\vdots
B_{Q} C_{Q}

Output

Print Q integers S_{i} to Standard Output in the following format:

S_{1}
S_{2}
\vdots
S_{Q}

Note that S_{i} may not fit into a 32-bit integer.

Sample Input 1

4
1 2 3 4
3
1 2
3 4
2 4

Sample Output 1

11
12
16

Initially, the sequence A is 1,2,3,4.

After each operation, it becomes the following:

2, 2, 3, 4

2, 2, 4, 4

4, 4, 4, 4

Sample Input 2

4
1 1 1 1
3
1 2
2 1
3 5

Sample Output 2

8
4
4

Note that the sequence A may not contain an element whose value is B_{i}.

Sample Input 3

2
1 2
3
1 100
2 100
100 1000

Sample Output 3

102
200
2000

Solution in C# (.NET Core 3.1.201) (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var n = long.Parse(Console.ReadLine());
        var a = Console.ReadLine().Split(' ').Select(long.Parse).ToArray();
        var q = long.Parse(Console.ReadLine());

        var tree = new SegmentTree<long>(a, (x, y) => x + y, 0);

        var results = new List<long>();

        for (int i= 0; i < q; i++)
        {
            var bc = Console.ReadLine().Split(' ').Select(long.Parse).ToArray();
            var b = bc[0];
            var c = bc[1];

            var targets = new List<int>();

            for(int t = 0; t < a.Length; t++)
            {
                if(a[t] == b)
                {
                    a[t] = c;
                    targets.Add(t);
                }
            }

            foreach(var item in targets)
            {
                tree.Update(item, c);
            }
            results.Add(tree.Execute(0, a.Length));
        }

        foreach (var item in results) Console.WriteLine(item);

    }
}

public class SegmentTree<T>
{
    public int N { get; private set; }
    private T[] _tree;
    private readonly Func<T, T, T> _updateMethod;
    private readonly T _initValue;

    /// <summary>
    /// セグメント木の初期化
    /// </summary>
    /// <param name="items">要素達</param>
    /// <param name="updateMethod">更新する方法</param>
    /// <param name="initValue">セグメント木のノードの初期値</param>
    public SegmentTree(IEnumerable<T> items, Func<T, T, T> updateMethod, T initValue)
    {
        T[] array = items.ToArray();
        _updateMethod = updateMethod;
        _initValue = initValue;

        // セグ木の最下段は２の冪乗にする
        N = 1;
        while (N < array.Length) N *= 2;

        _tree = Enumerable.Repeat(initValue, 2 * N - 1).ToArray();

        // 最下段に要素達を入れた後、下の段から更新していく
        for (int i = 0; i < array.Length; i++) _tree[N + i - 1] = array[i];
        for (int i = N - 2; i >= 0; i--) _tree[i] = _updateMethod(_tree[2 * i + 1], _tree[2 * i + 2]);
    }

    /// <summary>
    /// 更新する
    /// </summary>
    /// <param name="i">更新したい値のインデックス</param>
    /// <param name="x">更新する値</param>
    public void Update(int i, T x)
    {
        // 更新したい要素のセグ木上でのインデックスを取得
        i = N + i - 1;

        // 値を更新した後に、どんどん親を更新していく
        _tree[i] = x;
        while (i > 0)
        {
            i = (i - 1) / 2;
            _tree[i] = _updateMethod(_tree[2 * i + 1], _tree[2 * i + 2]);
        }
    }

    /// <summary>
    /// 区間内の目的の値を取得する，要求区間[a, b)
    /// </summary>
    /// <param name="a">a以上の区間</param>
    /// <param name="b">b未満の区間</param>
    /// <returns></returns>
    public T Execute(int a, int b)
        => Execute(a, b, 0, 0, N);

    private T Execute(int a, int b, int k, int l, int r)
    {
        // 要求区間[a, b)に対して対象区間[l, r)を求める
        // 今いるノードのインデックスがk

        // 要求区間と対象区間が交わらない
        if (r <= a || b <= l) return _initValue;

        // 要求区間が対象区間を完全に被覆
        if (a <= l && r <= b) return _tree[k];

        // 要求区間が対象区間の一部を被覆しているので、子について探索を行う
        // 新しい対象区間は、現在の対象区間を半分に割ったもの
        var vl = Execute(a, b, 2 * k + 1, l, (l + r) / 2);
        var vr = Execute(a, b, 2 * k + 2, (l + r) / 2, r);
        return _updateMethod(vl, vr);
    }
}