When you play the game of thrones, you win, or you die. There is no middle ground.

Cersei Lannister, A Game of Thrones by George R. R. Martin

There are n nobles, numbered from 1 to n. Noble i has a power of i. There are also m "friendships". A friendship between nobles a and b is always mutual.

A noble is defined to be vulnerable if both of the following conditions are satisfied: 

  * the noble has at least one friend, and 
  * all of that noble's friends have a higher power. 



You will have to process the following three types of queries. 

  1. Add a friendship between nobles u and v. 
  2. Remove a friendship between nobles u and v. 
  3. Calculate the answer to the following process. 



The process: all vulnerable nobles are simultaneously killed, and all their friendships end. Then, it is possible that new nobles become vulnerable. The process repeats itself until no nobles are vulnerable. It can be proven that the process will end in finite time. After the process is complete, you need to calculate the number of remaining nobles.

Note that the results of the process are not carried over between queries, that is, every process starts with all nobles being alive!

Input

The first line contains the integers n and m (1 ≤ n ≤ 2⋅ 10^5, 0 ≤ m ≤ 2⋅ 10^5) — the number of nobles and number of original friendships respectively.

The next m lines each contain the integers u and v (1 ≤ u,v ≤ n, u ≠ v), describing a friendship. No friendship is listed twice.

The next line contains the integer q (1 ≤ q ≤ 2⋅ {10}^{5}) — the number of queries. 

The next q lines contain the queries themselves, each query has one of the following three formats. 

  * 1 u v (1 ≤ u,v ≤ n, u ≠ v) — add a friendship between u and v. It is guaranteed that u and v are not friends at this moment. 
  * 2 u v (1 ≤ u,v ≤ n, u ≠ v) — remove a friendship between u and v. It is guaranteed that u and v are friends at this moment. 
  * 3 — print the answer to the process described in the statement. 

Output

For each type 3 query print one integer to a new line. It is guaranteed that there will be at least one type 3 query.

Examples

Input


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


Output


2
1


Input


4 3
2 3
3 4
4 1
1
3


Output


1

Note

Consider the first example. In the first type 3 query, we have the diagram below.

In the first round of the process, noble 1 is weaker than all of his friends (2 and 3), and is thus killed. No other noble is vulnerable in round 1. In round 2, noble 3 is weaker than his only friend, noble 4, and is therefore killed. At this point, the process ends, and the answer is 2.

<image>

In the second type 3 query, the only surviving noble is 4.

The second example consists of only one type 3 query. In the first round, two nobles are killed, and in the second round, one noble is killed. The final answer is 1, since only one noble survives.

<image>
3 0
2
1 2 1
3
 20 0
1
3
 1000 0
1
3
 20 0
20
3
3
1 17 19
1 19 20
1 4 8
1 9 18
1 1 14
1 16 19
1 10 19
1 1 7
1 6 10
1 18 19
1 9 16
1 15 17
1 11 12
1 10 15
3
1 2 9
1 1 13
1 16 20
 20 53
1 2
1 4
1 5
1 6
1 7
1 8
1 20
2 3
2 6
2 16
2 17
3 6
3 18
3 20
4 6
4 7
4 8
4 9
4 14
4 18
5 11
5 13
5 17
5 18
5 19
6 8
6 13
7 8
7 10
7 15
7 17
7 18
8 15
8 16
9 10
9 15
10 11
10 17
10 20
11 15
11 16
12 14
12 15
12 16
12 19
14 16
14 19
16 17
16 19
16 20
17 19
17 20
18 19
1
3

2
 20
 1000
 20
20
9
 4

import java.io.*;
import java.util.*;
import java.lang.*;

public class codeforces {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        if (System.getProperty("ONLINE_JUDGE") == null) {
            long startTime = System.currentTimeMillis();
            try {
                sc = new InputReader(new FileInputStream("input.txt"));
                out = new PrintWriter(new FileOutputStream("output.txt"));
                pr = new PrintWriter(new FileOutputStream("error.txt"));
            } catch (Exception ignored) {
            }
            int t = 1;
            int tt = t;
            // t = sc.nextInt();
            while (t-- > 0) {
                solve();
            }
            long endTime = System.currentTimeMillis();
            System.out.println("Time: " + (endTime - startTime) / tt + " ms");
            out.flush();
            pr.flush();

        } else {
            sc = new InputReader(inputStream);
            out = new PrintWriter(outputStream);
            pr = new PrintWriter(outputStream);
            int t = 1;
            // t = sc.nextInt();
            while (t-- > 0) {
                solve();
            }
            out.flush();
        }
    }

    public static void solve() {
        int n = sc.nextInt();
        int m = sc.nextInt();
        Set<Pair>set=new HashSet<>();
        Pair[] pairs = new Pair[(int) 1e5 * 2 + 10];
        int i = 0;
        for (i = 0; i < m; i++) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            pairs[i] = new Pair(a, b);
        }
        int q = sc.nextInt();
        for (int j = 0; j < q; j++) {
            // Arrays.sort(pairs, new Comparator<Pair>() {
            // @Override
            // public int compare(Pair p1, Pair p2) {
            // return Integer.compare(p1.first, p2.first);
            // }
            // });
            int x = sc.nextInt();
            if (x == 3)
                out.println(calcScore(pairs, m));
            if (x == 1) {
                pairs[i++] = new Pair(sc.nextInt(), sc.nextInt());
                m++;
            }
            if (x == 2) {
                remove(pairs, sc.nextInt(), sc.nextInt(), m);
            }
        }
    }

    public static void remove(Pair[] pairs, int a, int b, int m) {
        for (int i = 0; i < m; i++) {
            if ((a != pairs[i].first && b != pairs[i].second) || b != pairs[i].first && a != pairs[i].second) {
                continue;
            } else
                pairs[i] = new Pair(minf, minf);
        }
    }

    public static int calcScore(Pair[] pairs, int m) {
        Set<Integer> removed = new HashSet<>();
        Set<Integer> list = new HashSet<>();
        for (int i = 0; i < m; i++) {
            int a = pairs[i].first;
            int b = pairs[i].second;
            if (a != minf) {
                int max = Math.max(a, b);
                int min = Math.min(a, b);
                removed.add(min);
                if (!removed.contains(max))
                    list.add(max);
            }
        }
        Iterator value = list.iterator();
        int count = 0;
        while (value.hasNext()) {
            if (removed.contains(value.next()))
                count++;
        }
        return list.size() - count;
    }

    /*******************************************************************/
    /*
     * Iterator value = set.iteratoputr(); Displaying the values after iterating
     * through the iterator System.out.println("The iterator values are: "); while
     * (value.hasNext()) { System.out.println(value.next()); }
     */

    // Map Iterator:
    // for (Map.Entry<Integer, Integer> entry : map.entrySet()){}

    // pair sort
    // Arrays.sort(lap, new Comparator<Pair>() {
    // @Override
    // public int compare(Pair p1, Pair p2) {
    // return Integer.compare(p1.first, p2.first);

    // }
    // });

    // Globals

    public static int inf = Integer.MAX_VALUE;
    public static int minf = Integer.MIN_VALUE;
    public static int mod = 1000000007;
    public static int ml = (int) 1e9;
    public static InputReader sc;
    public static PrintWriter out;
    public static PrintWriter pr;

    // Pair

    static class Pair {
        int first, second;

        Pair(int x, int y) {
            this.first = x;
            this.second = y;
        }
    }

    // FastReader Class

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }

    // Node class

    static class Node {
        Node next;
        int data;

        Node(int x) {
            next = null;
            this.data = x;
        }
    }

    // Req Functions

    public static int gcd(int a, int b) {
        if (a == 0)
            return b;
        return gcd(b % a, a);
    }

    public static int lcm(int a, int b) {
        return (a / gcd(a, b)) * b;
    }

    public static long gcd(long a, long b) {
        if (a == 0)
            return b;
        return gcd(b % a, a);
    }

    public static long lcm(long a, long b) {
        return (a / gcd(a, b)) * b;
    }

    static long nCr(int n, int r) {
        return fact(n) / (fact(r) * fact(n - r));
    }

    static long fact(int n) {
        int res = 1;
        for (int i = 2; i <= n; i++)
            res = res * i;
        return res;
    }

    static long nCr(long n, long r) {
        return fact(n) / (fact(r) * fact(n - r));
    }

    static long fact(long n) {
        int res = 1;
        for (int i = 2; i <= n; i++)
            res = res * i;
        return res;
    }

    public static String reverseString(String input) {
        StringBuilder str = new StringBuilder("");

        for (int i = input.length() - 1; i >= 0; i--) {
            str.append(input.charAt(i));
        }
        return str.toString();
    }

    public static int maxOf3(int x, int y, int z) {
        return Math.max(x, Math.max(y, z));
    }

    public static int minof3(int x, int y, int z) {
        return Math.min(x, Math.min(y, z));
    }

    public static long maxOf3(long x, long y, long z) {
        return Math.max(x, Math.max(y, z));
    }

    public static long minof3(long x, long y, long z) {
        return Math.min(x, Math.min(y, z));
    }

    public static void arrInput(int[] arr, int n) {
        for (int i = 0; i < n; i++)
            arr[i] = sc.nextInt();
    }

    public static void arrInput(long[] arr, int n) {
        for (int i = 0; i < n; i++)
            arr[i] = sc.nextLong();
    }

    public static void arrInput(Pair[] pair, int n) {
        for (int i = 0; i < n; i++)
            pair[i] = new Pair(sc.nextInt(), sc.nextInt());
    }

    public static int lowerBound(int[] arr, int x) {
        int l = -1, r = arr.length;
        while (l + 1 < r) {
            int m = (l + r) >>> 1;
            if (arr[m] >= x)
                r = m;
            else
                l = m;
        }
        return r;
    }

    public static int upperBound(int[] arr, int x) {
        int l = -1, r = arr.length;
        while (l + 1 < r) {
            int m = (l + r) >>> 1;
            if (arr[m] <= x)
                l = m;
            else
                r = m;
        }
        return l + 1;
    }

    public static void fill(char[][] arr, char c) {
        int n = arr.length, m = arr[0].length;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                arr[i][j] = c;
    }

    public static void fill(int[][] arr, int c) {
        int n = arr.length, m = arr[0].length;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                arr[i][j] = c;
    }

    public static void fill(long[][] arr, long c) {
        int n = arr.length, m = arr[0].length;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                arr[i][j] = c;
    }

    public static void merge(int arr[], int l, int m, int r) {
        int n1 = m - l + 1;
        int n2 = r - m;
        int L[] = new int[n1];
        int R[] = new int[n2];
        for (int i = 0; i < n1; ++i)
            L[i] = arr[l + i];
        for (int j = 0; j < n2; ++j)
            R[j] = arr[m + 1 + j];
        int i = 0, j = 0;
        int k = l;
        while (i < n1 && j < n2) {
            if (L[i] >= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
            k++;
        }
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }
        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

    public static void reversesort(int arr[], int l, int r) {
        if (l < r) {
            int m = l + (r - l) / 2;
            reversesort(arr, l, m);
            reversesort(arr, m + 1, r);
            merge(arr, l, m, r);
        }
    }

    public static void merge(long arr[], int l, int m, int r) {
        int n1 = m - l + 1;
        int n2 = r - m;
        long L[] = new long[n1];
        long R[] = new long[n2];
        for (int i = 0; i < n1; ++i)
            L[i] = arr[l + i];
        for (int j = 0; j < n2; ++j)
            R[j] = arr[m + 1 + j];
        int i = 0, j = 0;
        int k = l;
        while (i < n1 && j < n2) {
            if (L[i] >= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
            k++;
        }
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }
        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

    public static void reversesort(long arr[], int l, int r) {
        if (l < r) {
            int m = l + (r - l) / 2;
            reversesort(arr, l, m);
            reversesort(arr, m + 1, r);
            merge(arr, l, m, r);
        }
    }

    public static void sort(int[] arr) {
        Arrays.sort(arr);
    }

    public static void sort(long[] arr) {
        Arrays.sort(arr);
    }

    public static void sort(ArrayList<Integer> list) {
        Collections.sort(list);
    }

    public static long sumint(int n) {
        long ans = 0;
        char[] s = String.valueOf(n).toCharArray();
        for (int i = 0; i < s.length; ++i)
            ans += s[i] - '0';
        return ans;
    }

    public static long sumint(long n) {
        long ans = 0;
        char[] s = String.valueOf(n).toCharArray();
        for (int i = 0; i < s.length; ++i)
            ans += s[i] - '0';
        return ans;
    }

    // debug

    public static void debug() {
        if (sysFlag)
            pr.println("");
    }

    public static boolean sysFlag = System.getProperty("ONLINE_JUDGE") == null;

    public static void debug(int[][] dp) {
        if (sysFlag) {
            for (int i = 0; i < dp.length; ++i) {
                pr.print(i + "--> ");
                for (int j = 0; j < dp[0].length; ++j) {
                    pr.print(dp[i][j] + " ");
                }
                pr.println("");
            }
        }
    }

    public static void debug(char[][] arr) {
        if (sysFlag) {
            for (int i = 0; i < arr.length; ++i) {
                for (int j = 0; j < arr[0].length; ++j) {
                    pr.print(arr[i][j]);
                }
                pr.println("");
            }
        }
    }

    public static void debug(long[][] dp) {
        if (sysFlag) {
            for (int i = 0; i < dp.length; ++i) {
                pr.print(i + "--> ");
                for (int j = 0; j < dp[0].length; ++j) {
                    pr.print(dp[i][j] + " ");
                }
                pr.println("");
            }
        }
    }

    public static void debug(int x) {
        if (sysFlag)
            pr.println("Int-Ele: " + x);
    }

    public static void debug(String x) {
        if (sysFlag)
            pr.println("String: " + x);
    }

    public static void debug(char x) {
        if (sysFlag)
            pr.println("Char: " + x);
    }

    public static void debug(long x) {
        if (sysFlag)
            pr.println("Long-Ele: " + x);
    }

    public static void debug(int[] arr) {
        if (sysFlag) {
            for (int i = 0; i < arr.length; ++i) {
                pr.println(i + " -> " + arr[i]);
            }
        }
    }

    public static void debug(char[] arr) {
        if (sysFlag) {
            for (int i = 0; i < arr.length; ++i) {
                pr.println(i + " -> " + arr[i]);
            }
        }
    }

    public static void debug(long[] arr) {
        if (sysFlag) {
            for (int i = 0; i < arr.length; ++i) {
                pr.println(i + " -> " + arr[i]);
            }
        }
    }

    public static void debug(ArrayList<Integer> list) {
        if (sysFlag) {
            for (int i = 0; i < list.size(); ++i) {
                pr.println(i + " -> " + list.get(i));
            }
        }
    }

    public static void Ldebug(ArrayList<Long> list) {
        if (sysFlag) {
            for (int i = 0; i < list.size(); ++i) {
                pr.println(i + " -> " + list.get(i));
            }
        }
    }

    public static void debugmapII(HashMap<Integer, Integer> map) {
        if (sysFlag) {
            for (Map.Entry<Integer, Integer> entry : map.entrySet())
                pr.println("Key => " + entry.getKey() + ", Value => " + entry.getValue());
        }
    }

    public static void debugmapLI(HashMap<Long, Integer> map) {
        if (sysFlag) {
            for (Map.Entry<Long, Integer> entry : map.entrySet())
                pr.println("Key => " + entry.getKey() + ", Value => " + entry.getValue());
        }
    }

    public static void debugmapLL(HashMap<Long, Long> map) {
        if (sysFlag) {
            for (Map.Entry<Long, Long> entry : map.entrySet())
                pr.println("Key => " + entry.getKey() + ", Value => " + entry.getValue());
        }
    }

    public static void debugmapIL(HashMap<Integer, Long> map) {
        if (sysFlag) {
            for (Map.Entry<Integer, Long> entry : map.entrySet())
                pr.println("Key => " + entry.getKey() + ", Value => " + entry.getValue());
        }
    }

    public static void debugmapSL(HashMap<String, Long> map) {
        if (sysFlag) {
            for (Map.Entry<String, Long> entry : map.entrySet())
                pr.println("Key => " + entry.getKey() + ", Value => " + entry.getValue());
        }
    }

    public static void debugmapCL(HashMap<Character, Long> map) {
        if (sysFlag) {
            for (Map.Entry<Character, Long> entry : map.entrySet())
                pr.println("Key => " + entry.getKey() + ", Value => " + entry.getValue());
        }
    }

    public static void debugmapSI(HashMap<String, Integer> map) {
        if (sysFlag) {
            for (Map.Entry<String, Integer> entry : map.entrySet())
                pr.println("Key => " + entry.getKey() + ", Value => " + entry.getValue());
        }
    }

    public static void debugmapCI(HashMap<Character, Integer> map) {
        if (sysFlag) {
            for (Map.Entry<Character, Integer> entry : map.entrySet())
                pr.println("Key => " + entry.getKey() + ", Value => " + entry.getValue());
        }
    }

    public static void debug(Set<Integer> set) {
        if (sysFlag) {
            Iterator value = set.iterator();
            int i = 1;
            while (value.hasNext()) {
                pr.println((i++) + "-> " + value.next());
            }
        }
    }

    public static void debug(Pair[] pair, int n) {
        if (sysFlag) {
            for (int i = 0; i < n; i++) {
                pr.println("first:" + pair[i].first + " second:" + pair[i].second);
            }
        }
    }
}
