import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author ijxjdjd
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Cards solver = new Cards();
        solver.solve(1, in, out);
        out.close();
    }

    static class Cards {
        long MOD = 998244353;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            long N = in.nextInt();
            long M = in.nextInt();
            int K = in.nextInt();
            long mod = MathUtils.modFraction(1, M, MOD);
            long[] expect = new long[K + 1];
            expect[0] = 1;
            long[] poly = new long[K + 1];
            poly[0] = 1;
            long curExpect = 1;
            for (int k = 1; k <= K; k++) {
                curExpect *= (N - (k - 1));
                curExpect %= MOD;
                curExpect *= mod;
                curExpect %= MOD;
                for (int i = k; i >= 0; i--) {
                    poly[i] = (i > 0 ? poly[i - 1] : 0) + (-(k - 1)) * poly[i];
                    poly[i] = MathUtils.mod(poly[i], MOD);
                }
                expect[k] = curExpect;
                for (int i = k - 1; i >= 0; i--) {
                    expect[k] -= poly[i] * expect[i];
                    expect[k] = MathUtils.mod(expect[k], MOD);
                }
            }
            out.println(expect[K]);
        }

    }

    static class MathUtils {
        public static long inverse(long a, long mod) {
            long[] inv = extended_gcd(a, mod);
            if (inv[0] != 1) {
                return 0;
            } else {
                return (inv[1] + 2 * mod) % mod;
            }
        }

        public static long modFraction(long a, long b, long mod) {
            //a is numerator, b is denominator
            long invB = inverse(b, mod);
            if (invB == 0) {
                return -1;
            } else {
                return (invB * a) % mod;
            }
        }

        public static long[] extended_gcd(long a, long b) {
            //three numbers, first is gcd, second is x, third is y
            if (a == 0) {
                return new long[]{b, 0, 1};
            }
            long[] next = extended_gcd(b % a, a);
            long tempX = next[1];
            next[1] = next[2] - (b / a) * next[1];
            next[2] = tempX;
            return next;
        }

        public static long mod(long a, long mod) {
            return (a + (Math.abs(a) + mod - 1) / mod * mod) % mod;
        }

    }

    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());
        }

    }
}


import java.io.*;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.*;

public class q5 {
	static long[][] dp;
	static int m,n;
	static long mod=998244353;
	static long modPow(long a, long b) {
		long res=1;
		while(b>0) {
			if((b&1)==1) res*=a;
			res%=mod;
			a*=a;a%=mod;b/=2;
		}
		return res;
	}

	static long solve(int k, int b) {
		if(k==0) {
			return modPow(m,n-b);
		}
		if(dp[k][b]==-1) {
			if(b==0) {
				dp[k][b]= (n)* solve(k-1,b+1);
				dp[k][b]%=mod;
			}
			else if(b==n) {
				dp[k][b]=b*solve(k-1,b);
			}
			else {
				dp[k][b]=(b*solve(k-1,b))%mod+ ((n-b)*solve(k-1,b+1))%mod;;
			}
		}
		dp[k][b]%=mod;
		return dp[k][b];
	}
	public static void main(String[] args) throws IOException {

		Reader.init(System.in);
		PrintWriter out=new PrintWriter(System.out);
		n=Reader.nextInt();m=Reader.nextInt();
		int k=Reader.nextInt();
		dp=new long[k+5][k+5];
		for(int i=0;i<=k;i++) {
			Arrays.fill(dp[i], -1);
		}
		long ans=solve(k,0);
		ans*= modPow(modPow(m,n),mod-2);
		ans%=mod;
		out.println(ans);

		out.flush();
	}
 }

class Reader {
    static BufferedReader reader;
    static StringTokenizer tokenizer;
    /** call this method to initialize reader for InputStream */
    static void init() throws IOException {
    	 reader = new BufferedReader(
                 new FileReader("input.txt"));
    tokenizer = new StringTokenizer("");
    }
    static void init(InputStream input) {
        reader = new BufferedReader(
                     new InputStreamReader(input) );
        tokenizer = new StringTokenizer("");
    }
    /** get next word */
    static String nextLine() throws IOException{
    	return reader.readLine();
    }
    static String next() throws IOException {
        while ( ! tokenizer.hasMoreTokens() ) {
            //TODO add check for eof if necessary
            tokenizer = new StringTokenizer(
                   reader.readLine() );
        }
        return tokenizer.nextToken();
    }
    static int nextInt() throws IOException {
        return Integer.parseInt( next() );
    }
    static long nextLong() throws IOException {
        return Long.parseLong( next() );
    }
    static double nextDouble() throws IOException {
        return Double.parseDouble( next() );
    }
}


// Coached by rainboy
// https://codeforces.com/contest/1278/submission/67223059 (rainboy)
import java.io.*;
import java.util.*;

public class CF1278F extends PrintWriter {
	CF1278F() { super(System.out, true); }
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF1278F o = new CF1278F(); o.main(); o.flush();
	}

	static final int MD = 998244353;
	int d_, x_, y_;
	void gcd_(int a, int b) {
		if (b == 0) {
			d_ = a; x_ = 1; y_ = 0;
		} else {
			gcd_(b, a % b);
			int t = x_ - a / b * y_; x_ = y_; y_ = t;
		}
	}
	int inv(int a) {
		gcd_(a, MD);
		return x_ < 0 ? x_ + MD : x_;
	}
	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt(), m_ = inv(m);
		int k = sc.nextInt();
		int[] dp = new int[k + 1]; dp[0] = 1;
		for (int h = 0; h < k; h++)
			for (int d = k - 1; d >= 0; d--)
				if (dp[d] != 0) {
					dp[d + 1] = (int) ((dp[d + 1] + (long) dp[d] * (n - d)) % MD);
					dp[d] = (int) ((long) dp[d] * d % MD);
				}
		long p = 1, ans = 0;
		for (int d = 1; d <= k; d++) {
			p = p * m_ % MD;
			ans = (ans + dp[d] * p) % MD;
		}
		println(ans);
	}
}


import java.util.*;
import java.io.*;
import java.math.BigInteger;
import java.text.*;

public class F1278 {

	static long[][] comb; // may need BigInteger, if the numbers are large, use a treemap

	static long modInverse(long a, long mod) {
		return BigInteger.valueOf(a).modInverse(BigInteger.valueOf(mod)).longValue();
	}

	static long modPow(long a, long e, long mod) // O(log e)
	{
		a %= mod;
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1)
				res = (res * a) % mod;
			a = (a * a) % mod;
			e >>= 1;
		}
		return res;
	}

//	static long nCr1(int n, int k) {
//		if (n < k)
//			return 0;
//		if (k == 0 || k == n)
//			return 1;
//		if (comb[n][k] != -1)
//			return comb[n][k];
//		if (n - k < k)
//			return comb[n][k] = nCr1(n, n - k);
//		return comb[n][k] = ((nCr1(n - 1, k - 1) + nCr1(n - 1, k)) % mod);
//	}

	static long mod = 998244353;

//	static long sum(long n, long k, long m) {
//		long sum = 0;
//		for (int i = 0; i <= n; i++) {
//			long w = modPow(i, k, mod);
//			w *= nCr1((int) n, i) % mod;
//			w %= mod;
//			w *= modPow(m - 1,i, mod);
//			w %= mod;
//			sum += w;
//			sum %= mod;
//		}
//		System.out.println(sum);
//		sum *= modPow(modInverse(m, mod), n, mod);
//		sum %= mod;
//		return sum;
//	}

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		PrintWriter pw = new PrintWriter(System.out);
		long n = sc.nextInt();
		long m = sc.nextInt();
		int k = sc.nextInt();
//		comb = new long[(int) n + 1][(int) n + 1];
//		for (long[] xx : comb)
//			Arrays.fill(xx, -1);
		long[] c = new long[k];
		long[] nP = new long[k + 1];
		nP[0] = 1;
		for (int i = 1; i <= k; i++) {
			nP[i] = ((n - i + 1) * nP[i - 1]) % mod;
		}
		c[0] = 1;
		for (int i = 0; i < k; i++) {
			long mult = 1;
			for (int j = i; j > 0; j--) {
				c[j] += (mult * c[j - 1]) % mod;
				c[j] %= mod;
				mult++;
			}
		}
		long ans = 0;
		for (int i = 0; i < k; i++) {
			long w = 1;
			w *= c[i] * nP[k - i];
			w %= mod;
			w *= modPow(m, n - (k - i), mod);
			w %= mod;
			ans += w;
			ans %= mod;
//			pw.println(ans);
		}
//		pw.println(ans);
		ans *= modPow(modInverse(m, mod), n, mod);
		ans %= mod;
//		pw.println(Arrays.toString(nP));
//		pw.println(Arrays.toString(c));
		pw.println(ans);
//		pw.println(sum(n, k, m));
		pw.close();
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s) {
			br = new BufferedReader(new InputStreamReader(s));
		}

		public Scanner(FileReader r) {
			br = new BufferedReader(r);
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

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

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

		public String nextLine() throws IOException {
			return br.readLine();
		}

		public double nextDouble() throws IOException {
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if (x.charAt(0) == '-') {
				neg = true;
				start++;
			}
			for (int i = start; i < x.length(); i++)
				if (x.charAt(i) == '.') {
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				} else {
					sb.append(x.charAt(i));
					if (dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg ? -1 : 1);
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

	}
}


import java.io.*;
import java.math.BigInteger;
import java.util.StringTokenizer;

/**
 * Author: homo_sapiens
 * Date: 7/14/12
 * Time: 11:54 AM
 */
public class Solution {
    public static void main(String[] args) throws IOException {
        Solution solution = new Solution();
        solution.run();
    }

    private int n;
    private int[] a;
    private BigInteger[][][] z;

    private void run() throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

        String s = in.readLine();

        a = new int[s.length()];
        for (int i = 0; i < s.length(); i++) {
            a[i] = s.charAt(i) == 'A' ? 0 : 1;
        }

        z = new BigInteger[s.length() + 1][4][4];

        for (int i = 0; i <= s.length(); i++) {
            for (int j = 0; j < 4; j++) {
                for (int k = 0; k < 4; k++) {
                    z[i][j][k] = BigInteger.valueOf(-1);
                }
            }
        }

        BigInteger result = BigInteger.ZERO;

        for (int mask = 0; mask < 4; mask++) {
            result = result.add(solve(2, mask, mask));
        }

        out.write(result.toString());
        out.newLine();

        out.close();
        in.close();
    }

    private BigInteger solve(int idx, int mask1, int mask2) {
        if (!z[idx][mask1][mask2].equals(BigInteger.valueOf(-1))) {
            return z[idx][mask1][mask2];
        }

        int f1 = mask1 & 1, f2 = (mask1 >> 1) & 1;
        int s1 = mask2 & 1, s2 = (mask2 >> 1) & 1;

        BigInteger result = BigInteger.ZERO;

        if (idx == a.length) {
            if (correct(s1, s2, f1, a[idx - 2], a[idx - 1], a[0])
                    && correct(s2, f1, f2, a[idx - 1], a[0], a[1])) {
                result = BigInteger.ONE;
            }
        } else {
            for (int cur = 0; cur < 2; cur++) {
                if (correct(s1, s2, cur, a[idx - 2], a[idx - 1], a[idx])) {
                    result = result.add(solve(idx + 1, mask1, (cur << 1) | s2));
                }
            }
        }

        return z[idx][mask1][mask2] = result;
    }

    private boolean correct(int a1, int a2, int a3, int b1, int b2, int b3) {
        if (a1 == 0 && a2 == 1) {
            return b1 == 1 && b2 == 0;
        } else if (a2 == 0 && a3 == 1) {
            return b2 == 1 && b3 == 0;
        } else {
            return a2 == b2;
        }
    }
}


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

public class C {
	static void p(Object ...o) {System.out.println(Arrays.deepToString(o));};
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String S = in.next();
		System.out.println(solution(S));
//		for (int N = 3; N <= 10; N++) {
//			for (int i = 0; i < (1<<N); i++) {
//				String S = "";
//				for (int j = 0; j < N; j++) {
//					if ((i&(1<<j)) != 0)
//						S += "B";
//					else
//						S += "A";
//				}
//				long ans1 = solution(S);
//				long ans2 = solution2(S);
//				if (ans1 != ans2) {
//					System.out.println("ERROR!!" + S+" "+ans1+" "+ans2);
//				}
//			}
//		}
		//		System.out.println(solution("BAABA"));
		//		System.out.println(solution2("BAABA"));
	}
	static String go(String S) {
		String ans = "";
		boolean wrap = false;
		if (S.charAt(S.length()-1) == 'A' && S.charAt(0) == 'B')
			wrap = true;
		for (int i = 0; i < S.length(); i++) {
			if (i == 0 && wrap) {
				ans += "A";
			} else if (i == S.length() -1 && wrap) {
				ans += "B";
			} else if (i + 1 < S.length() && S.charAt(i) == 'A' && S.charAt(i+1) == 'B') {
				ans += "BA";
				i++;
			} else {
				ans += S.charAt(i);
			}
		}
		return ans;
	}
	static long solution2(String T) {
		int N = T.length();
		long ans = 0;
		for (int i = 0; i < (1<<N); i++) {
			String S = "";
			for (int j = 0; j < N; j++) {
				if ((i&(1<<j)) != 0)
					S += "B";
				else
					S += "A";
			}
			if (go(S).equals(T)) {
				//				p("\t", S, go(S));
				ans++;
			}
		}
		return ans;
	}
	static long solution(String S) {
		String A = make_swap(S);
		if (A.charAt(A.length()-1) == 'B' && A.charAt(0) == 'A')
			A = "S"+A.substring(1, A.length()-1);
		char[] C = A.toCharArray();
//		p(A);
		int N = C.length;
		for (int i = 0; i < N ;i++) {
			if (C[i] == 'A' && C[(i+1)%N] == 'B')
				return 0;
		}
		DP = new long[2][2][N+1];
		for (int i = 0; i < 2; i++)
			for(int j = 0; j < 2; j++)
				Arrays.fill(DP[i][j], -1);
		long ans = 1;
		for (int i = 0; i < N; i++) {
			if (C[(i+N-1)%N] != 'S' && C[i] == 'S') {
				int len = 1;
				while (len < N && C[(i+len)%N] == 'S') {
					len++;
				}
				char before = C[(i+N-1)%N];
				char after = C[(i+len)%N];
				ans *= solve(before == 'A' ? 1 :0, after == 'B' ? 1 :0, len);
			}
		}
		boolean allS = true;
		for (int i = 0; i < N ;i++)
			if (C[i] != 'S')
				allS = false;
		if (allS)
			ans = solve(0, 0, N-1) + solve(1, 1, N-1);
		return ans;
	}
	static long[][][] DP;
	private static long solve(int before, int after, int len) {
		//		p(before, after, len);
		if (DP[before][after][len] != -1)
			return DP[before][after][len];
		long ans = 0;
		if (len == 1) {
			if(before == 0 && after == 0)
				ans = 2;
			else
				ans = 1;
		} else {
			if (before == 0) {
				ans += solve(1, after, len-1);
			}
			ans += solve(0, after, len-1);
		}
		DP[before][after][len] = ans;
		return ans;
	}
	static String make_swap(String S) {
		String A = "";
		for (int i = 0; i < S.length(); i++) {
			if (i +1 < S.length() && S.charAt(i) == 'B' && S.charAt(i+1) == 'A') {
				A += "S";
				i++;
			} else {
				A += S.charAt(i);
			}
		}
		return A;
	}
}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.StringTokenizer;

/**
 * Created with IntelliJ IDEA.
 * User: contest
 * Date: 7/14/12
 * Time: 11:36 AM
 * To change this template use File | Settings | File Templates.
 */
public class problemC {
    final String prefix = "c";
    final String problem_input = prefix + ".in";
    final String problem_output = prefix + ".out";
    BufferedReader br;
    StringTokenizer st;
    PrintWriter out;
    String s;
    BigInteger dp[][];
    void load() throws IOException
    {
        s = nextToken();
    }
    int first;

    BigInteger f(int i, int m)
    {
        if (i == s.length())
        {
            if (m == first)
                return BigInteger.ONE;
            else return BigInteger.ZERO;
        }
        if (dp[i][m] != null) return dp[i][m];
        dp[i][m] = BigInteger.ZERO;
        if (s.charAt(i) == 'A')
        {
            if ((m & 1) == 0) // _A
            {
                dp[i][m] = dp[i][m].add(f(i + 1, ((m << 1) | 0) & 3));
            }
            else //_B
            {
                if ((m & 2) == 0)
                    for (int j = 0; j < 2; j++)
                        dp[i][m] = dp[i][m].add(f(i + 1, ((m << 1) | j) & 3));
            }
        }
        else if (s.charAt(i) == 'B')
        {
            if ((m & 1) == 1) // _B
            {                    //BB
                if ((m & 2) > 0) // B
                {
                    for (int j = 0; j < 2; j++)
                        dp[i][m] = dp[i][m].add(f(i + 1, ((m << 1) | j) & 3));
                }
            }
            else // _A
            {
                dp[i][m] = f(i + 1, ((m << 1) | 1) & 3);
            }
        }
        return dp[i][m];
    }
    void solve()
    {
        dp = new BigInteger[s.length() + 2][4];
        BigInteger res = BigInteger.ZERO;
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < s.length() + 1; j++)
                dp[j][0] = dp[j][1] = dp[j][2] = dp[j][3] = null;
            first = i;
            res = res.add(f(0, i));
        }
        out.println(res);
    }
    void run()
    {
        try
        {
            br = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(new OutputStreamWriter(System.out));
            load();
            solve();
            out.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
            System.exit(42);
        }
    }
    public String nextToken() throws IOException {
        while (st == null || !st.hasMoreTokens())
        {
            st = new StringTokenizer(br.readLine());
        }
        return st.nextToken();
    }
    public int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }
    public long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }
    public double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
    public void readIntArray(int []a, int n) throws IOException
    {
        for (int i = 0; i < n; i++)
            a[i] = nextInt();
    }
    public static void main(String args[])
    {
        new problemC().run();
    }
}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.StringTokenizer;

/**
 * Created with IntelliJ IDEA.
 * User: contest
 * Date: 7/14/12
 * Time: 11:36 AM
 * To change this template use File | Settings | File Templates.
 */
public class problemC {
    final String prefix = "c";
    final String problem_input = prefix + ".in";
    final String problem_output = prefix + ".out";
    BufferedReader br;
    StringTokenizer st;
    PrintWriter out;
    String s;
    BigInteger dp[][];
    void load() throws IOException
    {
        s = nextToken();
    }
    int first;

    BigInteger f(int i, int m)
    {
        if (i == s.length())
        {
            if (m == first)
                return BigInteger.ONE;
            else return BigInteger.ZERO;
        }
        if (dp[i][m] != null) return dp[i][m];
        dp[i][m] = BigInteger.ZERO;
        if (s.charAt(i) == 'A')
        {
            if ((m & 1) == 0) // _A
            {
                dp[i][m] = dp[i][m].add(f(i + 1, ((m << 1) | 0) & 3));
            }
            else //_B
            {
                if ((m & 2) == 0)
                    for (int j = 0; j < 2; j++)
                        dp[i][m] = dp[i][m].add(f(i + 1, ((m << 1) | j) & 3));
            }
        }
        else if (s.charAt(i) == 'B')
        {
            if ((m & 1) == 1) // _B
            {                    //BB
                if ((m & 2) > 0) // B
                {
                    for (int j = 0; j < 2; j++)
                        dp[i][m] = dp[i][m].add(f(i + 1, ((m << 1) | j) & 3));
                }
            }
            else // _A
            {
                dp[i][m] = f(i + 1, ((m << 1) | 1) & 3);
            }
        }
        return dp[i][m];
    }
    void solve()
    {
        dp = new BigInteger[s.length() + 2][4];
        BigInteger res = BigInteger.ZERO;
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < s.length() + 1; j++)
                dp[j][0] = dp[j][1] = dp[j][2] = dp[j][3] = null;
            first = i;
            res = res.add(f(0, i));
        }
        out.println(res);
    }
    void run()
    {
        try
        {
            br = new BufferedReader(new FileReader(problem_input));
            out = new PrintWriter(problem_output);
            load();
            solve();
            out.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
            System.exit(42);
        }
    }
    public String nextToken() throws IOException {
        while (st == null || !st.hasMoreTokens())
        {
            st = new StringTokenizer(br.readLine());
        }
        return st.nextToken();
    }
    public int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }
    public long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }
    public double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
    public void readIntArray(int []a, int n) throws IOException
    {
        for (int i = 0; i < n; i++)
            a[i] = nextInt();
    }
    public static void main(String args[])
    {
        new problemC().run();
    }
}


import java.util.*;

public class E {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		int a = sc.nextInt(), b = sc.nextInt(), p = sc.nextInt();
		long x = sc.nextLong();

		long arr[] = new long[p];
		arr[p-1] = 1;
		for(int i=p-2;i>=0;i--){
			arr[i] = arr[i+1] * a % p;
		}

		long ans = 0;
		long T = (long)p*(p-1);

		for(int i = 1;i<=p-1;i++){
			long j = (i- b * arr[i]) % p;
			while(j < 0){
				j+=p;
			}

			long n = j * (p-1) + i;

			while(n <= x){
				ans ++;
				n += T;
			}
		}

		System.out.println(ans);

	}

}


import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.TreeSet;

public final class CF_460_E{

	static boolean verb=true;
	static void log(Object X){if (verb) System.err.println(X);}
	static void log(Object[] X){if (verb) {for (Object U:X) System.err.print(U+" ");System.err.println("");}}
	static void log(int[] X){if (verb) {for (int U:X) System.err.print(U+" ");System.err.println("");}}
	static void log(int[] X,int L){if (verb) {for (int i=0;i<L;i++) System.err.print(X[i]+" ");System.err.println("");}}
	static void log(long[] X){if (verb) {for (long U:X) System.err.print(U+" ");System.err.println("");}}

	static void logWln(Object X){if (verb) System.err.print(X);}
	static void info(Object o){	System.out.println(o);}
	static void output(Object o){outputWln(""+o+"\n");	}
	static void outputWln(Object o){try {out.write(""+ o);} catch (Exception e) {}}

	static long mod=1000000007;
	static long MX=1000000000000000001L;

	// Global vars
	static BufferedWriter out;
	static InputReader reader;

	static long powerMod(long b,long e,long m){
		long x=1;
		while (e>0) {
			if (e%2==1)
				x=(b*x)%m;
			b=(b*b)%m;
			e=e/2;
		}
		return x;
	}

	static void process() throws Exception {

		out = new BufferedWriter(new OutputStreamWriter(System.out));
		reader=new InputReader(System.in);

		int a=reader.readInt();
		int b=reader.readInt();
		int p=reader.readInt();
		long x=reader.readLong();

		long pp=p;

		ArrayList<Integer>[] targy=new ArrayList[p];
		ArrayList<Integer>[] targk=new ArrayList[p];
		for (int u=1;u<p;u++){
			targy[u]=new ArrayList<Integer>();
			targk[u]=new ArrayList<Integer>();

		}

		for (int y=1;y<p;y++){
			long yay=powerMod(a,y,p);
			yay*=y;
			yay%=p;
			long inv=powerMod(yay,p-2,p);
			long fin=inv*b;
			fin%=p;
			targy[(int)fin].add(y);
		}
		for (int k=0;k<p-1;k++){
			long ak=powerMod(a,k,p);
			targk[(int)ak].add(k);
		}
		long sum=0;
		for (int u=1;u<p;u++){
			if (targy[u].size()>0 && targk[u].size()>0){
				for (long k:targk[u])
					for (long y:targy[u]){

						if (p*k+y<=x){
							long mt=(x-y-pp*k)/(pp*(pp-1));
							sum+=mt+1;
						}

						/*
						long t=0;
						while (((p-1)*t+k)*p+y<=x){
							t++;
							sum++;
						}
						*/

					}
			}
		}
		output(sum);

		try {
			out.close();
		}
		catch (Exception EX){}

	}

	public static void main(String[] args) throws Exception {
		process();

	}

	static final class InputReader {
		private final InputStream stream;
		private final byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		private int read() throws IOException {
			if (curChar >= numChars) {
				curChar = 0;
				numChars = stream.read(buf);
				if (numChars <= 0) {
					return -1;
				}
			}
			return buf[curChar++];
		}

		public final String readString() throws IOException {
			int c = read();
			while (isSpaceChar(c)) {
				c = read();
			}
			StringBuilder res=new StringBuilder();
			do {
				res.append((char)c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public final int readInt() throws IOException {
			int c = read();
			boolean neg=false;
			while (isSpaceChar(c)) {
				c = read();
			}
			char d=(char)c;
			//log("d:"+d);
			if (d=='-') {
				neg=true;
				c = read();
			}
			int res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			//log("res:"+res);
			if (neg)
				return -res;
			return res;

		}

		public final long readLong() throws IOException {
			int c = read();
			boolean neg=false;
			while (isSpaceChar(c)) {
				c = read();
			}
			char d=(char)c;
			//log("d:"+d);
			if (d=='-') {
				neg=true;
				c = read();
			}
			long res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			//log("res:"+res);
			if (neg)
				return -res;
			return res;

		}

		private boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}
	}

}


import java.util.Scanner;

public class E {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        int a = in.nextInt();
        int b = in.nextInt();
        int p = in.nextInt();
        int x = in.nextInt();

        int answer = 0;
        for (int i = 0; i < p; i++) {
            int tmp = (b * modPow(modPow(a, i, p), p - 2, p)) % p;
            if (i >= tmp) {
                int first = (i - tmp) * (p-1) + i;
                if (first <= x)
                    answer += (x - first) / (p*(p-1)) + 1;
            }
        }

        System.out.println(answer);
    }

    private static int modPow(int a, int b, int mod) {
        int modPow = 1;
        for (; b > 0; b >>= 1) {
            if ((b & 1) != 0)
                modPow = (int) ((1L * modPow * a) % mod);
            a = (int) ((1L * a * a) % mod);
        }
        return modPow;
    }

}


import java.util.Scanner;

public class E {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        int a = in.nextInt();
        int b = in.nextInt();
        int p = in.nextInt();
        long x = in.nextInt();

        int answer = 0;
        for (int i = 0; i < p; i++) {
            int tmp = (b * modPow(modPow(a, i, p), p - 2, p)) % p;
            if (i >= tmp) {
                int first = (i - tmp) * (p-1) + i;
                if (first <= x)
                    answer += (x - first) / (p*(p-1)) + 1;
            }
        }

        System.out.println(answer);
    }

    private static int modPow(int a, int b, int mod) {
        int modPow = 1;
        for (; b > 0; b >>= 1) {
            if ((b & 1) != 0)
                modPow = (int) ((1L * modPow * a) % mod);
            a = (int) ((1L * a * a) % mod);
        }
        return modPow;
    }

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            int numQueries = in.nextInt();
            int[] p = new int[n];
            for (int i = 0; i < n; i++) {
                p[i] = -in.nextInt();
            }
            int[] a = new int[m];
            int[] b = new int[m];
            for (int i = 0; i < m; i++) {
                a[i] = in.nextInt() - 1;
                b[i] = in.nextInt() - 1;
            }
            int[] type = new int[numQueries];
            int[] val = new int[numQueries];
            boolean[] willDie = new boolean[m];
            for (int i = 0; i < numQueries; i++) {
                type[i] = in.nextInt();
                val[i] = in.nextInt() - 1;
                if (type[i] == 2) {
                    willDie[val[i]] = true;
                }
            }

            int[] parent = new int[n];
            Arrays.fill(parent, -1);
            DSU dsu = new DSU(n);
            Graph g = new Graph(n + 1);
            for (int i = 0; i < m; i++) {
                if (willDie[i]) {
                    continue;
                }
                int u = dsu.findComp(a[i]);
                int v = dsu.findComp(b[i]);
                if (u == v) {
                    continue;
                }
                dsu.merge(u, v);
                if (dsu.p[v] == u) {
                    int t = u;
                    u = v;
                    v = t;
                }
                parent[u] = v;
                g.addEdge(v, u, i);
            }

            for (int i = numQueries - 1; i >= 0; i--) {
                if (type[i] == 1) {
                    val[i] = dsu.findComp(val[i]);
                    continue;
                }
                int u = dsu.findComp(a[val[i]]);
                int v = dsu.findComp(b[val[i]]);
                if (u == v) {
                    continue;
                }
                dsu.merge(u, v);
                if (dsu.p[v] == u) {
                    int t = u;
                    u = v;
                    v = t;
                }
                parent[u] = v;
                g.addEdge(v, u, val[i]);
            }

            int root = n;
            for (int i = 0; i < n; i++) {
                if (parent[i] < 0) {
                    g.addEdge(root, i, -1);
                }
            }
            EulerTourNumbering et = new EulerTourNumbering(g, root);

            MinTree mt = new MinTree(n + 1);
            int[] q = new int[n + 1];
            for (int i = 0; i < n; i++) {
                q[et.timeIn[i]] = p[i];
                mt.set(et.timeIn[i], p[i]);
            }

            boolean[] dead = new boolean[m];
            int[] left = new int[n + 1];
            int[] right = new int[n + 1];
            for (int i = 0; i < left.length; i++) {
                left[i] = et.timeIn[i];
                right[i] = et.timeOut[i] - 1;
            }
            for (int i = 0; i < numQueries; i++) {
                if (type[i] == 2) {
                    dead[val[i]] = true;
                    continue;
                }
                int r = val[i];
                for (int e = g.firstEdge[val[i]]; e >= 0; e = g.edgeNxt[e]) {
                    int origId = g.edgeId[e];
                    int dst = g.edgeDst[e];
                    if (dead[origId]) {
                        if (e != g.firstEdge[val[i]]) {
                            throw new AssertionError();
                        }
                        g.firstEdge[val[i]] = g.edgeNxt[e];
                        left[val[i]] = et.timeOut[dst];
                    } else {
                        break;
                    }
                }
                int pos = et.timeIn[r];
                if (left[r] <= right[r]) {
                    int cand = mt.getMinPos(left[r], right[r]);
                    if (q[pos] > q[cand]) {
                        pos = cand;
                    }
                }
                out.println(-q[pos]);
                q[pos] = 0;
                mt.set(pos, 0);
            }
        }

        class EulerTourNumbering {
            Graph g;
            int[] tour;
            int[] timeIn;
            int[] timeOut;
            int globalTime;

            EulerTourNumbering(Graph g, int root) {
                this.g = g;
                int n = g.n;
                timeIn = new int[n];
                timeOut = new int[n];
                tour = new int[n];

                dfs(root, -1);
                if (globalTime != n) {
                    throw new AssertionError();
                }
            }

            void dfs(int v, int p) {
                tour[globalTime] = v;
                timeIn[v] = globalTime++;
                for (int e = g.firstEdge[v]; e >= 0; e = g.edgeNxt[e]) {
                    int u = g.edgeDst[e];
                    if (u == p) {
                        continue;
                    }
                    dfs(u, v);
                }
                timeOut[v] = globalTime;
            }

        }

        class Graph {
            int n;
            int[] firstEdge;
            int[] edgeDst;
            int[] edgeNxt;
            int[] edgeId;
            int numEdges;

            Graph(int n) {
                this.n = n;
                firstEdge = new int[n];
                Arrays.fill(firstEdge, -1);
                final int initialCapacity = 2 * n - 2;
                edgeDst = new int[initialCapacity];
                edgeNxt = new int[initialCapacity];
                edgeId = new int[initialCapacity];
                numEdges = 0;
            }

            void addEdge(int a, int b, int origId) {
                int e = numEdges++;
                if (e >= edgeDst.length) {
                    reallocate();
                }
                edgeDst[e] = b;
                edgeNxt[e] = firstEdge[a];
                firstEdge[a] = e;
                edgeId[e] = origId;
            }

            private void reallocate() {
                int k = edgeDst.length;
                edgeDst = Arrays.copyOf(edgeDst, 3 * k / 2);
                edgeNxt = Arrays.copyOf(edgeNxt, 3 * k / 2);
                edgeId = Arrays.copyOf(edgeId, 3 * k / 2);
            }

        }

        class MinTree {
            int n;
            int[] a;
            int[] where;
            final int infinity = (int) 1e9;

            MinTree(int size) {
                n = 1;
                while (n < size) {
                    n *= 2;
                }
                a = new int[2 * n];
                where = new int[2 * n];
                Arrays.fill(a, infinity);
            }

            void set(int pos, int val) {
                pos += n;
                a[pos] = val;
                where[pos] = pos - n;
                while (pos > 1) {
                    pos /= 2;
                    a[pos] = Math.min(a[2 * pos], a[2 * pos + 1]);
                    if (a[pos] == a[2 * pos]) {
                        where[pos] = where[2 * pos];
                    } else {
                        where[pos] = where[2 * pos + 1];
                    }
                }
            }

            int getMinPos(int l, int r) {
                if (l > r) {
                    return infinity;
                }
                l += n;
                r += n;
                if (l == r) {
                    return where[l];
                }
                int lm = a[l];
                int rm = a[r];
                int lp = where[l];
                int rp = where[r];
                while (r - l > 1) {
                    if (l % 2 == 0) {
                        if (lm > a[l + 1]) {
                            lm = a[l + 1];
                            lp = where[l + 1];
                        }
                    }
                    if (r % 2 != 0) {
                        if (rm > a[r - 1]) {
                            rm = a[r - 1];
                            rp = where[r - 1];
                        }
                    }
                    l /= 2;
                    r /= 2;
                }
                return lm < rm ? lp : rp;
            }

        }

        class DSU {
            int[] rank;
            int[] p;
            int numComps;

            DSU(int n) {
                rank = new int[n];
                p = new int[n];
                reset();
            }

            void reset() {
                for (int i = 0; i < p.length; i++) {
                    rank[i] = 0;
                    p[i] = i;
                }
                numComps = p.length;
            }

            private int findComp(int x) {
                int r;
                int saved;

                saved = x;
                while (x != p[x]) {
                    x = p[x];
                }
                r = x;

                x = saved;
                while (x != r) {
                    saved = p[x];
                    p[x] = r;
                    x = saved;
                }
                return r;
            }

            private void merge(int a, int b) {
                a = findComp(a);
                b = findComp(b);
                if (a == b) {
                    return;
                }
                --numComps;
                if (rank[a] < rank[b]) {
                    p[a] = b;
                } else {
                    p[b] = a;
                    if (rank[a] == rank[b]) {
                        ++rank[a];
                    }
                }
            }

        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

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

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

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            int numQueries = in.nextInt();
            int[] p = new int[n];
            for (int i = 0; i < n; i++) {
                p[i] = -in.nextInt();
            }
            int[] a = new int[m];
            int[] b = new int[m];
            for (int i = 0; i < m; i++) {
                a[i] = in.nextInt() - 1;
                b[i] = in.nextInt() - 1;
            }
            int[] type = new int[numQueries];
            int[] val = new int[numQueries];
            boolean[] willDie = new boolean[m];
            for (int i = 0; i < numQueries; i++) {
                type[i] = in.nextInt();
                val[i] = in.nextInt() - 1;
                if (type[i] == 2) {
                    willDie[val[i]] = true;
                }
            }

            int[] parent = new int[n];
            Arrays.fill(parent, -1);
            DSU dsu = new DSU(n);
            Graph g = new Graph(n + 1);
            for (int i = 0; i < m; i++) {
                if (willDie[i]) {
                    continue;
                }
                int u = dsu.findComp(a[i]);
                int v = dsu.findComp(b[i]);
                if (u == v) {
                    continue;
                }
                dsu.merge(u, v);
                if (dsu.p[v] == u) {
                    int t = u;
                    u = v;
                    v = t;
                }
                parent[u] = v;
                g.addEdge(v, u, i);
            }

            for (int i = numQueries - 1; i >= 0; i--) {
                if (type[i] == 1) {
                    val[i] = dsu.findComp(val[i]);
                    continue;
                }
                int u = dsu.findComp(a[val[i]]);
                int v = dsu.findComp(b[val[i]]);
                if (u == v) {
                    continue;
                }
                parent[u] = v;
                dsu.merge(u, v);
                if (dsu.p[v] == u) {
                    int t = u;
                    u = v;
                    v = t;
                }
                g.addEdge(v, u, i);
            }

            int root = n;
            for (int i = 0; i < n; i++) {
                if (parent[i] < 0) {
                    g.addEdge(root, i, -1);
                }
            }
            EulerTourNumbering et = new EulerTourNumbering(g, root);

            MinTree mt = new MinTree(n + 1);
            int[] q = new int[n + 1];
            for (int i = 0; i < n; i++) {
                q[et.timeIn[i]] = p[i];
                mt.set(et.timeIn[i], p[i]);
            }

            boolean[] dead = new boolean[m];
            for (int i = 0; i < numQueries; i++) {
                if (type[i] == 2) {
                    dead[val[i]] = true;
                    continue;
                }
                int pos = et.timeIn[val[i]];
                int l = pos;
                int r = pos;
                for (int e = g.firstEdge[val[i]]; e >= 0; e = g.edgeNxt[e]) {
                    int origId = g.edgeId[e];
                    int dst = g.edgeDst[e];
                    if (dead[origId]) {
                        if (l >= 0) {
                            int cand = mt.getMinPos(l, r);
                            if (q[pos] > q[cand]) {
                                pos = cand;
                            }
                            l = -1;
                        }
                        continue;
                    }
                    if (l < 0) {
                        l = et.timeIn[dst];
                    }
                    r = et.timeOut[dst] - 1;
                }
                if (l >= 0) {
                    int cand = mt.getMinPos(l, r);
                    if (q[pos] > q[cand]) {
                        pos = cand;
                    }
                    l = -1;
                }
                out.println(-q[pos]);
                q[pos] = 0;
                mt.set(pos, 0);
            }
        }

        class EulerTourNumbering {
            Graph g;
            int[] tour;
            int[] timeIn;
            int[] timeOut;
            int globalTime;

            EulerTourNumbering(Graph g, int root) {
                this.g = g;
                int n = g.n;
                timeIn = new int[n];
                timeOut = new int[n];
                tour = new int[n];

                dfs(root, -1);
                if (globalTime != n) {
                    throw new AssertionError();
                }
            }

            void dfs(int v, int p) {
                tour[globalTime] = v;
                timeIn[v] = globalTime++;
                for (int e = g.firstEdge[v]; e >= 0; e = g.edgeNxt[e]) {
                    int u = g.edgeDst[e];
                    if (u == p) {
                        continue;
                    }
                    dfs(u, v);
                }
                timeOut[v] = globalTime;
            }

        }

        class Graph {
            int n;
            int[] firstEdge;
            int[] edgeDst;
            int[] edgeNxt;
            int[] edgeId;
            int numEdges;

            Graph(int n) {
                this.n = n;
                firstEdge = new int[n];
                Arrays.fill(firstEdge, -1);
                final int initialCapacity = 2 * n - 2;
                edgeDst = new int[initialCapacity];
                edgeNxt = new int[initialCapacity];
                edgeId = new int[initialCapacity];
                numEdges = 0;
            }

            void addEdge(int a, int b, int origId) {
                int e = numEdges++;
                if (e >= edgeDst.length) {
                    reallocate();
                }
                edgeDst[e] = b;
                edgeNxt[e] = firstEdge[a];
                firstEdge[a] = e;
                edgeId[e] = origId;
            }

            private void reallocate() {
                int k = edgeDst.length;
                edgeDst = Arrays.copyOf(edgeDst, 3 * k / 2);
                edgeNxt = Arrays.copyOf(edgeNxt, 3 * k / 2);
                edgeId = Arrays.copyOf(edgeId, 3 * k / 2);
            }

        }

        class MinTree {
            int n;
            int[] a;
            int[] where;
            final int infinity = (int) 1e9;

            MinTree(int size) {
                n = 1;
                while (n < size) {
                    n *= 2;
                }
                a = new int[2 * n];
                where = new int[2 * n];
                Arrays.fill(a, infinity);
            }

            void set(int pos, int val) {
                pos += n;
                a[pos] = val;
                where[pos] = pos - n;
                while (pos > 1) {
                    pos /= 2;
                    a[pos] = Math.min(a[2 * pos], a[2 * pos + 1]);
                    if (a[pos] == a[2 * pos]) {
                        where[pos] = where[2 * pos];
                    } else {
                        where[pos] = where[2 * pos + 1];
                    }
                }
            }

            int getMinPos(int l, int r) {
                if (l > r) {
                    return infinity;
                }
                l += n;
                r += n;
                if (l == r) {
                    return where[l];
                }
                int lm = a[l];
                int rm = a[r];
                int lp = where[l];
                int rp = where[r];
                while (r - l > 1) {
                    if (l % 2 == 0) {
                        if (lm > a[l + 1]) {
                            lm = a[l + 1];
                            lp = where[l + 1];
                        }
                    }
                    if (r % 2 != 0) {
                        if (rm > a[r - 1]) {
                            rm = a[r - 1];
                            rp = where[r - 1];
                        }
                    }
                    l /= 2;
                    r /= 2;
                }
                return lm < rm ? lp : rp;
            }

        }

        class DSU {
            int[] rank;
            int[] p;
            int numComps;

            DSU(int n) {
                rank = new int[n];
                p = new int[n];
                reset();
            }

            void reset() {
                for (int i = 0; i < p.length; i++) {
                    rank[i] = 0;
                    p[i] = i;
                }
                numComps = p.length;
            }

            private int findComp(int x) {
                int r;
                int saved;

                saved = x;
                while (x != p[x]) {
                    x = p[x];
                }
                r = x;

                x = saved;
                while (x != r) {
                    saved = p[x];
                    p[x] = r;
                    x = saved;
                }
                return r;
            }

            private void merge(int a, int b) {
                a = findComp(a);
                b = findComp(b);
                if (a == b) {
                    return;
                }
                --numComps;
                if (rank[a] < rank[b]) {
                    p[a] = b;
                } else {
                    p[b] = a;
                    if (rank[a] == rank[b]) {
                        ++rank[a];
                    }
                }
            }

        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

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

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

    }
}


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

public class E {
	FastScanner in;
	PrintWriter out;
	boolean systemIO = true;

	public class DSU {
		int[] sz;
		int[] p;

		public DSU(int n) {
			sz = new int[n];
			p = new int[n];
			for (int i = 0; i < p.length; i++) {
				p[i] = i;
				sz[i] = 1;
			}
		}

		public int get(int x) {
			if (x == p[x]) {
				return x;
			}
			int par = get(p[x]);
			p[x] = par;
			return par;
		}

		public boolean unite(int a, int b) {
			int pa = get(a);
			int pb = get(b);
			if (pa == pb) {
				return false;
			}
			if (sz[pa] < sz[pb]) {
				p[pa] = pb;
				sz[pb] += sz[pa];
			} else {
				p[pb] = pa;
				sz[pa] += sz[pb];
			}
			return true;
		}
	}

	public class SegmentTreeAdd {
		int pow;
		long[] max;
		long[] delta;
		boolean[] flag;

		public SegmentTreeAdd(long[] a) {
			pow = 1;
			while (pow < a.length) {
				pow *= 2;
			}
			flag = new boolean[2 * pow];
			max = new long[2 * pow];
			delta = new long[2 * pow];
			for (int i = 0; i < max.length; i++) {
				max[i] = Long.MIN_VALUE / 2;
			}
			for (int i = 0; i < a.length; i++) {
				max[pow + i] = a[i];
			}
			for (int i = pow - 1; i > 0; i--) {
				max[i] = f(max[2 * i], max[2 * i + 1]);
			}
		}

		public long get(int v, int tl, int tr, int l, int r) {
			push(v, tl, tr);
			if (l > r) {
				return Long.MIN_VALUE / 2;
			}
			if (l == tl && r == tr) {
				return max[v];
			}
			int tm = (tl + tr) / 2;
			return f(get(2 * v, tl, tm, l, Math.min(r, tm)), get(2 * v + 1, tm + 1, tr, Math.max(l, tm + 1), r));
		}

		public void set(int v, int tl, int tr, int l, int r, long x) {
			push(v, tl, tr);
			if (l > tr || r < tl) {
				return;
			}
			if (l <= tl && r >= tr) {
				delta[v] += x;
				flag[v] = true;
				push(v, tl, tr);
				return;
			}
			int tm = (tl + tr) / 2;
			set(2 * v, tl, tm, l, r, x);
			set(2 * v + 1, tm + 1, tr, l, r, x);
			max[v] = f(max[2 * v], max[2 * v + 1]);
		}

		public void push(int v, int tl, int tr) {
			if (flag[v]) {
				if (v < pow) {
					flag[2 * v] = true;
					flag[2 * v + 1] = true;
					delta[2 * v] += delta[v];
					delta[2 * v + 1] += delta[v];
				}
				flag[v] = false;
				max[v] += delta[v];
				delta[v] = 0;
			}
		}

		public long f(long a, long b) {
			return Math.max(a, b);
		}
	}

	public class SegmentTreeSet {
		int pow;
		int[] sum;
		int[] delta;
		boolean[] flag;

		public SegmentTreeSet(int[] a) {
			pow = 1;
			while (pow < a.length) {
				pow *= 2;
			}
			flag = new boolean[2 * pow];
			sum = new int[2 * pow];
			delta = new int[2 * pow];
			for (int i = 0; i < a.length; i++) {
				sum[pow + i] = a[i];
			}
		}

		public int get(int v, int tl, int tr, int l, int r) {
			push(v, tl, tr);
			if (l > r) {
				return 0;
			}
			if (l == tl && r == tr) {
				return sum[v];
			}
			int tm = (tl + tr) / 2;
			return f(get(2 * v, tl, tm, l, Math.min(r, tm)), get(2 * v + 1, tm + 1, tr, Math.max(l, tm + 1), r));
		}

		public void set(int v, int tl, int tr, int l, int r, int x) {
			push(v, tl, tr);
			if (l > tr || r < tl) {
				return;
			}
			if (l <= tl && r >= tr) {
				delta[v] = x;
				flag[v] = true;
				push(v, tl, tr);
				return;
			}
			int tm = (tl + tr) / 2;
			set(2 * v, tl, tm, l, r, x);
			set(2 * v + 1, tm + 1, tr, l, r, x);
			sum[v] = f(sum[2 * v], sum[2 * v + 1]);
		}

		public void push(int v, int tl, int tr) {
			if (flag[v]) {
				if (v < pow) {
					flag[2 * v] = true;
					flag[2 * v + 1] = true;
					delta[2 * v] = delta[v];
					delta[2 * v + 1] = delta[v];
				}
				flag[v] = false;
				sum[v] = delta[v] * (tr - tl + 1);
			}
		}

		public int f(int a, int b) {
			return a + b;
		}
	}

	public class Pair implements Comparable<Pair> {
		int x;
		int y;

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

		public Pair clone() {
			return new Pair(x, y);
		}

		public String toString() {
			return x + " " + y;
		}

		@Override
		public int compareTo(Pair o) {
			if (y > o.y) {
				return 1;
			}
			if (y < o.y) {
				return -1;
			}
			if (x > o.x) {
				return 1;
			}
			if (x < o.x) {
				return -1;
			}
			return 0;
		}
	}

	long mod = 1000000007;
	Random random = new Random();

	public void shuffle(Pair[] a) {
		for (int i = 0; i < a.length; i++) {
			int x = random.nextInt(i + 1);
			Pair t = a[x];
			a[x] = a[i];
			a[i] = t;
		}
	}

	public void sort(int[][] a) {
		for (int i = 0; i < a.length; i++) {
			Arrays.sort(a[i]);
		}
	}

	public void add(HashMap<Long, Integer> map, long l) {
		if (map.containsKey(l)) {
			map.put(l, map.get(l) + 1);
		} else {
			map.put(l, 1);
		}
	}

	public void remove(TreeMap<Integer, Integer> map, Integer s) {
		if (map.get(s) > 1) {
			map.put(s, map.get(s) - 1);
		} else {
			map.remove(s);
		}
	}

	long max = Long.MAX_VALUE / 2;
	double eps = 1e-10;

	public int signum(double x) {
		if (x > eps) {
			return 1;
		}
		if (x < -eps) {
			return -1;
		}
		return 0;
	}

	public long abs(long x) {
		return x < 0 ? -x : x;
	}

	public long min(long x, long y) {
		return x < y ? x : y;
	}

	public long max(long x, long y) {
		return x > y ? x : y;
	}

	public long gcd(long x, long y) {
		while (y > 0) {
			long c = y;
			y = x % y;
			x = c;
		}
		return x;
	}

	public final Vector ZERO = new Vector(0, 0);

	// public class Vector implements Comparable<Vector> {
	// long x;
	// long y;
	// int type;
	// int number;
	//
	// public Vector() {
	// x = 0;
	// y = 0;
	// }
	//
	// public Vector(long x, long y, int type, int number) {
	// this.x = x;
	// this.y = y;
	// this.type = type;
	// this.number = number;
	// }
	//
	// public Vector(long x, long y) {
	//
	// }
	//
	// public Vector(Point begin, Point end) {
	// this(end.x - begin.x, end.y - begin.y);
	// }
	//
	// public void orient() {
	// if (x < 0) {
	// x = -x;
	// y = -y;
	// }
	// if (x == 0 && y < 0) {
	// y = -y;
	// }
	// }
	//
	// public void normalize() {
	// long gcd = gcd(abs(x), abs(y));
	// x /= gcd;
	// y /= gcd;
	// }
	//
	// public String toString() {
	// return x + " " + y;
	// }
	//
	// public boolean equals(Vector v) {
	// return x == v.x && y == v.y;
	// }
	//
	// public boolean collinear(Vector v) {
	// return cp(this, v) == 0;
	// }
	//
	// public boolean orthogonal(Vector v) {
	// return dp(this, v) == 0;
	// }
	//
	// public Vector ort(Vector v) {
	// return new Vector(-y, x);
	// }
	//
	// public Vector add(Vector v) {
	// return new Vector(x + v.x, y + v.y);
	// }
	//
	// public Vector multiply(long c) {
	// return new Vector(c * x, c * y);
	// }
	//
	// public int quater() {
	// if (x > 0 && y >= 0) {
	// return 1;
	// }
	// if (x <= 0 && y > 0) {
	// return 2;
	// }
	// if (x < 0) {
	// return 3;
	// }
	// return 0;
	// }
	//
	// public long len2() {
	// return x * x + y * y;
	// }
	//
	// @Override
	// public int compareTo(Vector o) {
	// if (quater() != o.quater()) {
	// return quater() - o.quater();
	// }
	// return signum(cp(o, this));
	// }
	// }

	// public long dp(Vector v1, Vector v2) {
	// return v1.x * v2.x + v1.y * v2.y;
	// }
	//
	// public long cp(Vector v1, Vector v2) {
	// return v1.x * v2.y - v1.y * v2.x;
	// }

	// public class Line implements Comparable<Line> {
	// Point p;
	// Vector v;
	//
	// public Line(Point p, Vector v) {
	// this.p = p;
	// this.v = v;
	// }
	//
	// public Line(Point p1, Point p2) {
	// if (p1.compareTo(p2) < 0) {
	// p = p1;
	// v = new Vector(p1, p2);
	// } else {
	// p = p2;
	// v = new Vector();
	// }
	// }
	//
	// public boolean collinear(Line l) {
	// return v.collinear(l.v);
	// }
	//
	// public boolean inLine(Point p) {
	// return hv(p) == 0;
	// }
	//
	// public boolean inSegment(Point p) {
	// if (!inLine(p)) {
	// return false;
	// }
	// Point p1 = p;
	// Point p2 = p.add(v);
	// return p1.x <= p.x && p.x <= p2.x && min(p1.y, p2.y) <= p.y && p.y <=
	// max(p1.y, p2.y);
	// }
	//
	// public boolean equalsSegment(Line l) {
	// return p.equals(l.p) && v.equals(l.v);
	// }
	//
	// public boolean equalsLine(Line l) {
	// return collinear(l) && inLine(l.p);
	// }
	//
	// public long hv(Point p) {
	// Vector v1 = new Vector(this.p, p);
	// return cp(v, v1);
	// }
	//
	// public double h(Point p) {
	// Vector v1 = new Vector(this.p, p);
	// return cp(v, v1) / Math.sqrt(v.len2());
	// }
	//
	// public long[] intersectLines(Line l) {
	// if (collinear(l)) {
	// return null;
	// }
	// long[] ans = new long[4];
	//
	// return ans;
	// }
	//
	// public long[] intersectSegment(Line l) {
	// long[] ans = intersectLines(l);
	// if (ans == null) {
	// return null;
	// }
	// Point p1 = p;
	// Point p2 = p.add(v);
	// boolean f1 = p1.x * ans[1] <= ans[0] && ans[0] <= p2.x * ans[1] && min(p1.y,
	// p2.y) * ans[3] <= ans[2]
	// && ans[2] <= max(p1.y, p2.y) * ans[3];
	// p1 = l.p;
	// p2 = l.p.add(v);
	// boolean f2 = p1.x * ans[1] <= ans[0] && ans[0] <= p2.x * ans[1] && min(p1.y,
	// p2.y) * ans[3] <= ans[2]
	// && ans[2] <= max(p1.y, p2.y) * ans[3];
	// if (!f1 || !f2) {
	// return null;
	// }
	// return ans;
	// }
	//
	// @Override
	// public int compareTo(Line o) {
	// return v.compareTo(o.v);
	// }
	// }

	public class Rect {
		long x1;
		long x2;
		long y1;
		long y2;
		int number;

		public Rect(long x1, long x2, long y1, long y2, int number) {
			this.x1 = x1;
			this.x2 = x2;
			this.y1 = y1;
			this.y2 = y2;
			this.number = number;
		}
	}

	public static class Fenvik {
		int[] t;

		public Fenvik(int n) {
			t = new int[n];
		}

		public void add(int x, int delta) {
			for (int i = x; i < t.length; i = (i | (i + 1))) {
				t[i] += delta;
			}
		}

		private int sum(int r) {
			int ans = 0;
			int x = r;
			while (x >= 0) {
				ans += t[x];
				x = (x & (x + 1)) - 1;
			}
			return ans;
		}

		public int sum(int l, int r) {
			return sum(r) - sum(l - 1);
		}
	}

	public class SegmentTreeMaxSum {
		int pow;
		int[] sum;
		int[] maxPrefSum;
		int[] maxSufSum;
		int[] maxSum;

		public SegmentTreeMaxSum(int[] a) {
			pow = 1;
			while (pow < a.length) {
				pow *= 2;
			}
			sum = new int[2 * pow];
			maxPrefSum = new int[2 * pow];
			maxSum = new int[2 * pow];
			maxSufSum = new int[2 * pow];
			for (int i = 0; i < a.length; i++) {
				sum[pow + i] = a[i];
				maxSum[pow + i] = Math.max(a[i], 0);
				maxPrefSum[pow + i] = maxSum[pow + i];
				maxSufSum[pow + i] = maxSum[pow + i];
			}
			for (int i = pow - 1; i > 0; i--) {
				update(i);
			}
		}

		public int[] get(int v, int tl, int tr, int l, int r) {
			if (r <= tl || l >= tr) {
				int[] ans = { 0, 0, 0, 0 };
				return ans;
			}
			if (l <= tl && r >= tr) {
				int[] ans = { maxPrefSum[v], maxSum[v], maxSufSum[v], sum[v] };
				return ans;
			}
			int tm = (tl + tr) / 2;
			int[] left = get(2 * v, tl, tm, l, r);
			int[] right = get(2 * v + 1, tm, tr, l, r);
			int[] ans = { Math.max(left[0], right[0] + left[3]),
					Math.max(left[1], Math.max(right[1], left[2] + right[0])), Math.max(right[2], left[2] + right[3]),
					left[3] + right[3] };
			return ans;
		}

		public void set(int v, int tl, int tr, int x, int value) {
			if (v >= pow) {
				sum[v] = value;
				maxSum[v] = Math.max(value, 0);
				maxPrefSum[v] = maxSum[v];
				maxSufSum[v] = maxSum[v];
				return;
			}
			int tm = (tl + tr) / 2;
			if (x < tm) {
				set(2 * v, tl, tm, x, value);
			} else {
				set(2 * v + 1, tm, tr, x, value);
			}
			update(v);
		}

		public void update(int i) {
			sum[i] = f(sum[2 * i], sum[2 * i + 1]);
			maxSum[i] = Math.max(maxSum[2 * i], Math.max(maxSum[2 * i + 1], maxSufSum[2 * i] + maxPrefSum[2 * i + 1]));
			maxPrefSum[i] = Math.max(maxPrefSum[2 * i], maxPrefSum[2 * i + 1] + sum[2 * i]);
			maxSufSum[i] = Math.max(maxSufSum[2 * i + 1], maxSufSum[2 * i] + sum[2 * i + 1]);
		}

		public int f(int a, int b) {
			return a + b;
		}
	}

	public class Point implements Comparable<Point> {
		double x;
		double y;

		public Point() {
			x = 0;
			y = 0;
		}

		public Point(double x, double y) {
			this.x = x;
			this.y = y;
		}

		public String toString() {
			return x + " " + y;
		}

		public boolean equals(Point p) {
			return x == p.x && y == p.y;
		}

		public double dist2() {
			return x * x + y * y;
		}

		public Point add(Point v) {
			return new Point(x + v.x, y + v.y);
		}

		@Override
		public int compareTo(Point o) {
			int z = signum(x + y - o.x - o.y);
			if (z != 0) {
				return z;
			}
			return signum(x - o.x) != 0 ? signum(x - o.x) : signum(y - o.y);
		}
	}

	public class Circle implements Comparable<Circle> {
		Point p;
		int r;

		public Circle(Point p, int r) {
			this.p = p;
			this.r = r;
		}

		public Point angle() {
			double z = r / sq2;
			z -= z % 1e-5;
			return new Point(p.x - z, p.y - z);
		}

		public boolean inside(Point p) {
			return hypot2(p.x - this.p.x, p.y - this.p.y) <= sq(r);
		}

		@Override
		public int compareTo(Circle o) {
			Point a = angle();
			Point oa = o.angle();
			int z = signum(a.x + a.y - oa.x - oa.y);
			if (z != 0) {
				return z;
			}
			return signum(a.y - oa.y);
		}

	}

	public class Fraction implements Comparable<Fraction> {
		long x;
		long y;

		public Fraction(long x, long y, boolean needNorm) {
			this.x = x;
			this.y = y;
			if (y < 0) {
				this.x *= -1;
				this.y *= -1;
			}
			if (needNorm) {
				long gcd = gcd(this.x, this.y);
				this.x /= gcd;
				this.y /= gcd;
			}
		}

		public Fraction clone() {
			return new Fraction(x, y, false);
		}

		public String toString() {
			return x + "/" + y;
		}

		@Override
		public int compareTo(Fraction o) {
			long res = x * o.y - y * o.x;
			if (res > 0) {
				return 1;
			}
			if (res < 0) {
				return -1;
			}
			return 0;
		}
	}

	public class Event implements Comparable<Event> {
		Fraction f;
		int type;

		public Event(Fraction f, int type) {
			this.f = f;
			this.type = type;
		}

		@Override
		public int compareTo(Event o) {
			int c = f.compareTo(o.f);
			if (c != 0) {
				return c;
			}
			return type - o.type;
		}

	}

	public double sq(double x) {
		return x * x;
	}

	public long sq(long x) {
		return x * x;
	}

	public double hypot2(double x, double y) {
		return sq(x) + sq(y);
	}

	public long hypot2(long x, long y) {
		return sq(x) + sq(y);
	}

	public boolean kuhn(int v, int[][] edge, boolean[] used, int[] mt) {
		used[v] = true;
		for (int u : edge[v]) {
			if (mt[u] < 0 || (!used[mt[u]] && kuhn(mt[u], edge, used, mt))) {
				mt[u] = v;
				return true;
			}
		}
		return false;
	}

	public int matching(int[][] edge) {
		int n = edge.length;
		int[] mt = new int[n];
		Arrays.fill(mt, -1);
		boolean[] used = new boolean[n];
		int ans = 0;
		for (int i = 0; i < n; i++) {
			if (!used[i] && kuhn(i, edge, used, mt)) {
				Arrays.fill(used, false);
				ans++;
			}
		}
		return ans;
	}

	double sq2 = Math.sqrt(2);

	int small = 20;

	public class Stack {
		int[] st;
		int sz;

		public Stack(int n) {
			this.st = new int[n];
			sz = 0;
		}

		public boolean isEmpty() {
			return sz == 0;
		}

		public int peek() {
			return st[sz - 1];
		}

		public int pop() {
			sz--;
			return st[sz];
		}

		public void clear() {
			sz = 0;
		}

		public void add(int x) {
			st[sz++] = x;
		}

		public int get(int x) {
			return st[x];
		}
	}

	public int[][] readGraph(int n, int m) {
		int[][] to = new int[n][];
		int[] sz = new int[n];
		int[] x = new int[m];
		int[] y = new int[m];
		for (int i = 0; i < m; i++) {
			x[i] = in.nextInt() - 1;
			y[i] = in.nextInt() - 1;
			sz[x[i]]++;
			sz[y[i]]++;
		}
		for (int i = 0; i < to.length; i++) {
			to[i] = new int[sz[i]];
			sz[i] = 0;
		}
		for (int i = 0; i < x.length; i++) {
			to[x[i]][sz[x[i]]++] = y[i];
			to[y[i]][sz[y[i]]++] = x[i];
		}
		return to;
	}

	public class Pol {
		double[] coeff;

		public Pol(double[] coeff) {
			this.coeff = coeff;
		}

		public Pol mult(Pol p) {
			double[] ans = new double[coeff.length + p.coeff.length - 1];
			for (int i = 0; i < ans.length; i++) {
				for (int j = Math.max(0, i - p.coeff.length + 1); j < coeff.length && j <= i; j++) {
					ans[i] += coeff[j] * p.coeff[i - j];
				}
			}
			return new Pol(ans);
		}

		public String toString() {
			String ans = "";
			for (int i = 0; i < coeff.length; i++) {
				ans += coeff[i] + " ";
			}
			return ans;
		}

		public double value(double x) {
			double ans = 0;
			double p = 1;
			for (int i = 0; i < coeff.length; i++) {
				ans += coeff[i] * p;
				p *= x;
			}
			return ans;
		}

		public double integrate(double r) {
			Pol p = new Pol(new double[coeff.length + 1]);
			for (int i = 0; i < coeff.length; i++) {
				p.coeff[i + 1] = coeff[i] / fact[i + 1];
			}
			return p.value(r);
		}

		public double integrate(double l, double r) {
			return integrate(r) - integrate(l);
		}
	}

	double[] fact = new double[100];

	public class DSU1 {
		int[] p;
		int[] sz;
		Stack less;
		Stack more;
		TreeSet<Integer>[] q;
		boolean[] used;

		@SuppressWarnings("unchecked")
		public DSU1(int[] v, int m) {
			int n = v.length;
			p = new int[n];
			sz = new int[n];
			q = new TreeSet[n];
			less = new Stack(m);
			more = new Stack(m);
			used = new boolean[n + 1];
			for (int i = 0; i < v.length; i++) {
				p[i] = i;
				sz[i] = 1;
				q[i] = new TreeSet<>();
				q[i].add(v[i]);
			}
		}

		public int get(int x) {
			while (x != p[x]) {
				x = p[x];
			}
			return x;
		}

		public boolean unite(int a, int b) {
			int pa = get(a);
			int pb = get(b);
			if (pa == pb) {
				less.add(-1);
				more.add(-1);
				return false;
			}
			if (sz[pa] < sz[pb]) {
				p[pa] = pb;
				sz[pb] += sz[pa];

				less.add(pa);
				more.add(pb);
				for (int i : q[pa]) {
					q[pb].add(i);
				}
			} else {
				p[pb] = pa;
				sz[pa] += sz[pb];

				less.add(pb);
				more.add(pa);
				for (int i : q[pb]) {
					q[pa].add(i);
				}
			}
			return true;
		}

		public void popEdge() {
			int pa = less.pop();
			int pb = more.pop();
			if (pa < 0) {
				return;
			}
			for (int i : q[pa]) {
				q[pb].remove(i);
			}
			p[pa] = pa;
			sz[pb] -= sz[pa];
		}

		public int poll(int x) {
			int px = get(x);
			while (!q[px].isEmpty()) {
				int v = q[px].pollLast();
				if (!used[v]) {
					used[v] = true;
					return v;
				}
			}
			return 0;
		}

	}

	public void solve() {
		int n = in.nextInt();
		int m = in.nextInt();
		int q = in.nextInt();
		int[] v = new int[n];
		for (int i = 0; i < v.length; i++) {
			v[i] = in.nextInt();
		}
		int[] a = new int[m];
		int[] b = new int[m];
		for (int i = 0; i < b.length; i++) {
			a[i] = in.nextInt() - 1;
			b[i] = in.nextInt() - 1;
		}
		boolean[] type = new boolean[q];
		int[] x = new int[q];
		boolean[] removed = new boolean[m];
		for (int i = 0; i < q; i++) {
			if (in.nextInt() == 1) {
				x[i] = in.nextInt() - 1;
				type[i] = true;
			} else {
				x[i] = in.nextInt() - 1;
				removed[x[i]] = true;
			}
		}
		DSU1 dsu = new DSU1(v, m);
		for (int i = 0; i < removed.length; i++) {
			if (!removed[i]) {
				dsu.unite(a[i], b[i]);
			}
		}
		for (int i = q - 1; i >= 0; i--) {
			if (!type[i]) {
				dsu.unite(a[x[i]], b[x[i]]);
			}
		}
		for (int i = 0; i < q; i++) {
			if (type[i]) {
				out.println(dsu.poll(x[i]));
			} else {
				dsu.popEdge();
			}
		}
	}

	public void add(HashMap<Integer, Integer> map, int x) {
		if (map.containsKey(x)) {
			map.put(x, map.get(x) + 1);
		} else {
			map.put(x, 1);
		}
	}

	public void run() {
		try {
			if (systemIO) {
				in = new FastScanner(System.in);
				out = new PrintWriter(System.out);
			} else {
				in = new FastScanner(new File("input.txt"));
				out = new PrintWriter(new File("output.txt"));
			}
			solve();

			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner(File f) {
			try {
				br = new BufferedReader(new FileReader(f));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}

		FastScanner(InputStream f) {
			br = new BufferedReader(new InputStreamReader(f));
		}

		String nextLine() {
			try {
				return br.readLine();
			} catch (IOException e) {
				return null;
			}
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

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

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

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

	}

	// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
	public static void main(String[] arg) {
		new E().run();
	}
}


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

/*
polyakoff
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 1e9 + 10;
    static final long OO = (long) 2e18 + 20;
    static final int MOD = (int) 1e9 + 7;

    static int n;
    static int[] par, p;

    static int findSet(int u) {
        if (par[u] == u)
            return u;
        return par[u] = findSet(par[u]);
    }

    static class SegTree {
        class Node {
            int max;
            Pair lr;

            Node(int max, Pair lr) {
                this.max = max;
                this.lr = lr;
            }
        }
        Node[] t;
        int size;

        void push(int u) {
            if (t[u].lr.l != -1) {
                t[u * 2 + 1].lr.l = t[u].lr.l;
                t[u * 2 + 1].lr.r = t[u].lr.r;
                t[u * 2 + 2].lr.l = t[u].lr.l;
                t[u * 2 + 2].lr.r = t[u].lr.r;
                t[u].lr.l = t[u].lr.r = -1;
            }
        }
        void pull(int u) {
            t[u].max = p[t[u * 2 + 1].max] > p[t[u * 2 + 2].max] ? t[u * 2 + 1].max : t[u * 2 + 2].max;
        }
        void build(int u, int tl, int tr, int[][] initial) {
            if (tl == tr) {
                t[u] = new Node(initial[tl][0], new Pair(initial[tl][1], initial[tl][2]));
            } else {
                int tm = (tl + tr) / 2;
                build(u * 2 + 1, tl, tm, initial);
                build(u * 2 + 2, tm + 1, tr, initial);
                t[u] = new Node(-1, new Pair(-1, -1));
                pull(u);
            }
        }
        int maxPOn(int u, int tl, int tr, int l, int r) {
            if (r < tl || tr < l)
                return n;
            if (l <= tl && tr <= r)
                return t[u].max;
            int tm = (tl + tr) / 2;
            push(u);
            int v1 = maxPOn(u * 2 + 1, tl, tm, l, r);
            int v2 = maxPOn(u * 2 + 2, tm + 1, tr, l, r);
            return p[v1] > p[v2] ? v1 : v2;
        }
        void setPIn(int u, int tl, int tr, int i, int p) {
            if (tl == tr) {

            } else {
                int tm = (tl + tr) / 2;
                push(u);
                if (i <= tm) {
                    setPIn(u * 2 + 1, tl, tm, i, p);
                } else {
                    setPIn(u * 2 + 2, tm + 1, tr, i, p);
                }
                pull(u);
            }
        }
        void setLROn(int u, int tl, int tr, int l, int r, int newL, int newR) {
            if (r < tl || tr < l)
                return;
            if (l <= tl && tr <= r) {
                t[u].lr.l = newL;
                t[u].lr.r = newR;
                return;
            }
            int tm = (tl + tr) / 2;
            push(u);
            setLROn(u * 2 + 1, tl, tm, l, r, newL, newR);
            setLROn(u * 2 + 2, tm + 1, tr, l, r, newL, newR);
            pull(u);
        }
        Pair LRIn(int u, int tl, int tr, int i) {
            if (tl == tr) {
                return t[u].lr;
            }
            int tm = (tl + tr) / 2;
            push(u);
            if (i <= tm) {
                return LRIn(u * 2 + 1, tl, tm, i);
            } else {
                return LRIn(u * 2 + 2, tm + 1, tr, i);
            }
        }

        void build(int[][] initial) {
            size = initial.length;
            t = new Node[size * 4];
            build(0, 0, size - 1, initial);
        }
        int maxPOn(int l, int r) {
            return maxPOn(0, 0, size - 1, l, r);
        }
        void setPIn(int i, int p) {
            setPIn(0, 0, size - 1, i, p);
        }
        void setLROn(int l, int r, int newL, int newR) {
            setLROn(0, 0, size - 1, l, r, newL, newR);
        }
        Pair LRIn(int i) {
            return LRIn(0, 0, size - 1, i);
        }
    }

    static class Pair {
        int l, r;

        Pair(int l, int r) {
            this.l = l;
            this.r = r;
        }
    }

    static class Edge {
        int u, v, l1, r1, l2, r2;
        boolean removed;

        Edge(int u, int v) {
            this.u = u;
            this.v = v;
            l1 = r1 = l2 = r2 = -1;
        }
    }

    static class Query {
        int type, x;

        Query(int type, int x) {
            this.type = type;
            this.x = x;
        }
    }

    static void solve() {
        n = in.nextInt();
        int m = in.nextInt();
        int q = in.nextInt();

        p = new int[n + 1];
        p[n] = 0;
        for (int i = 0; i < n; i++) {
            p[i] = in.nextInt();
        }

        Edge[] edges = new Edge[m];
        for (int i = 0; i < m; i++) {
            int u = in.nextInt() - 1;
            int v = in.nextInt() - 1;
            edges[i] = new Edge(u, v);
        }

        Query[] queries = new Query[q];
        for (int i = 0; i < q; i++) {
            int type = in.nextInt();
            int x = in.nextInt() - 1;
            queries[i] = new Query(type, x);
            if (type == 2)
                edges[x].removed = true;
        }

        par = new int[n];
        int[] size = new int[n];
        ArrayList<Integer>[] subtree = new ArrayList[n];
        for (int i = 0; i < n; i++) {
            par[i] = i;
            size[i] = 1;
            subtree[i] = new ArrayList<>(List.of(i));
        }

        for (Edge e : edges) {
            if (e.removed)
                continue;
            int u = findSet(e.u);
            int v = findSet(e.v);
            if (u == v)
                continue;
            if (size[u] < size[v]) {
                u ^= v; v ^= u; u ^= v;
            }
            par[v] = u;
            size[u] += size[v];
            subtree[u].addAll(subtree[v]);
        }

        for (int i = q - 1; i >= 0; i--) {
            Query query = queries[i];
            if (query.type == 1)
                continue;
            Edge e = edges[query.x];
            int u = findSet(e.u);
            int v = findSet(e.v);
            if (u == v)
                continue;
            if (size[u] < size[v]) {
                u ^= v; v ^= u; u ^= v;
            }
            par[v] = u;
            size[u] += size[v];
            e.l1 = subtree[u].get(0);
            e.r1 = subtree[u].get(subtree[u].size() - 1);
            e.l2 = subtree[v].get(0);
            e.r2 = subtree[v].get(subtree[v].size() - 1);
            subtree[u].addAll(subtree[v]);
        }

        int[][] initial = new int[n][3];
        int[] pos = new int[n];
        for (int u = 0, i = 0; u < n; u++) {
            if (findSet(u) == u) {
                initial[u][1] = i;
                initial[u][2] = i + size[u] - 1;
                for (int v : subtree[u]) {
                    initial[i][0] = v;
                    initial[i][1] = initial[u][1];
                    initial[i][2] = initial[u][2];
                    pos[v] = i;
                    i++;
                }
            }
        }

        SegTree st = new SegTree();
        st.build(initial);

        for (int i = 0; i < q; i++) {
            Query query = queries[i];
            if (query.type == 1) {
                int u = query.x;
                Pair lr = st.LRIn(pos[u]);
                int v = st.maxPOn(lr.l, lr.r);
                out.println(p[v]);
                if (v != n) {
                    p[v] = 0;
                    st.setPIn(pos[v], 0);
                }
            } else {
                Edge e = edges[query.x];
                if (e.l1 != -1) {
                    st.setLROn(pos[e.l1], pos[e.r1], pos[e.l1], pos[e.r1]);
                    st.setLROn(pos[e.l2], pos[e.r2], pos[e.l2], pos[e.r2]);
                }
            }
        }

    }

    public static void main(String[] args) {
        in = new FastReader();
        out = new PrintWriter(System.out);
//        fileInputOutput();

        int T = 1;
//        T = in.nextInt();
        while (T-- > 0)
            solve();

        out.flush();
        out.close();
    }

    static void fileInputOutput() {
        try {
            in = new FastReader("input.txt");
            out = new PrintWriter(new FileOutputStream("output.txt"));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    static void runInThread() {
        Thread thread = new Thread(null, () -> {
            int T = 1;
//            T = in.nextInt();
            while (T-- > 0)
                solve();
        }, "thread1", 1 << 28);
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader() {
            this(System.in);
        }
        FastReader(String file) throws FileNotFoundException {
            this(new FileInputStream(file));
        }
        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }
        String nextLine() {
            String line;
            try {
                line = br.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return line;
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;

public class E {

    static boolean DEBUG=false;
    static int N=1000;

    static class bits {
        int d,cnt;
        bits(int d, int cnt) {
            this.d=d; this.cnt=cnt;
        }
        long h(bits b) {
            if(d==b.d) {
                return Math.abs(cnt-b.cnt);
            } else {
                return Math.min(cnt, b.cnt)+Math.min(N-cnt, N-b.cnt);
            }
        }
        public String toString() {
            return d+":"+cnt;
        }
    }

    static long h(bits a, bits b, bits c) {
        return a.h(b)+b.h(c)+c.h(a);
    }

    static long maxh(bits[] in, int l, int r) {
        bits lb=in[l], rb=in[r];
        long max=-1;

        for (int i=0; i<in.length; i++) {
            if(i!=l&&i!=r) {
                long h=h(lb,rb,in[i]);
                if(h>max) {
                    max=h;
                }
            }
        }

        return max;
    }

    static long cnt_between(bits[] in, int l, int r, long max) {
        int l2=l, r2=r;
        while (l2+1<=r&&in[l2+1].cnt==in[l].cnt) {
            l2++;
        }
        while (r2-1>=l&&in[r2-1].cnt==in[r].cnt) {
            r2--;
        }

        if(l2>=r2) {
            return max==0? (long)(r-l)*(long)(r-l-1)*(long)(r-l-2)/6: 0;
        }

        long ret=0;
        for (int i=l+1; i<r; i++) {
            if(h(in[l],in[r],in[i])==max) {
                long v=(long)((i<=l2? l2-1: l2)-l+1)*(long)(r-(i>=r2? r2+1: r2)+1);
                ret+=v;
                if(DEBUG) {
                    System.out.println("added "+v+" for "+i+" in["+l+","+r+"]");
                }
            }
        }
        return ret;
    }

    static long cnt_pairs(int l1, int l2, int r1, int r2) {
        if(l2<r1) {
            return (long)(l2-l1+1)*(long)(r2-r1+1);
        } else {
            return (long)(r1-l1)*(long)(r2-l2)+
                    (long)(l2-r1+1)*(long)(r2-l2)+
                    (long)(r1-l1)*(long)(l2-r1+1)+
                    (long)(l2-r1+1)*(long)(l2-r1)/2;
        }
    }

    static long solve(bits[] in) {
        int n=in.length;
        Arrays.sort(in, new Comparator<bits>() {
            @Override
            public int compare(bits o1, bits o2) {
                int ret=o1.d-o2.d;
                if(ret==0) {
                    ret=o1.d==1? o1.cnt-o2.cnt: o2.cnt-o1.cnt;
                }
                return ret;
            }});

        int max0=-1;
        for (int i=0; i<n; i++) {
            if(in[i].d==0) {
                max0=i;
            }
        }

        if(max0<0||max0==n-1) {
            long maxh=maxh(in,0,n-1);
            return cnt_between(in, 0, n-1, maxh);
        } else {
            long maxh=Math.max(maxh(in,0,max0), maxh(in,max0+1,n-1));
            if(DEBUG) {
                System.out.println("maxh: "+maxh);
            }
            long ret=cnt_between(in, 0, max0, maxh);
            ret+=cnt_between(in, max0+1, n-1, maxh);

            int lo=n-2, hi=n-1;
            for (int i=0; i<=max0; i++) {
                if(h(in[max0+1],in[n-1],in[i])==maxh) {
                    while(lo-1>=max0+1&&in[lo].cnt>in[i].cnt) {
                        lo--;
                    }

                    while(hi-1>max0+1&&in[hi-1].cnt>=in[i].cnt) {
                        hi--;
                    }
                    long v=cnt_pairs(max0+1, lo, hi, n-1);
                    ret+=v;
                    if(DEBUG) {
                        System.out.println("added "+v+" for "+i+" out["+(max0+1)+","+(n-1)+"]");
                    }
                }
            }

            lo=0; hi=1;
            for (int i=n-1; i>=max0+1; i--) {
                if(h(in[0],in[max0],in[i])==maxh) {
                    while(lo+1<max0&&in[lo+1].cnt>=in[i].cnt) {
                        lo++;
                    }

                    while(hi+1<=max0&&in[hi].cnt>in[i].cnt) {
                        hi++;
                    }

                    long v=cnt_pairs(0, lo, hi, max0);
                    ret+=v;
                    if(DEBUG) {
                        System.out.println("added "+v+" for "+i+" out[0,"+max0+"]");
                    }
                }
            }
            return ret;
        }
    }

    static void run_stream(InputStream ins) throws IOException {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String[] nm=br.readLine().split(" ");
        N=Integer.parseInt(nm[0]);

        bits[] in=new bits[Integer.parseInt(nm[1])];
        for (int i=0; i<in.length; i++) {
            String l=br.readLine();

            in[i]=new bits(
                    Integer.parseInt(l.substring(0, 1)),
                    Integer.parseInt(l.substring(2)));
        }

        System.out.println(solve(in));
        //System.out.println(baseline(in));
    }

    public static void main(String[] args) throws IOException {
        run_stream(System.in);

        //run_random();
        //run();
    }

    static void run_random() {
        Random r=new Random();

        int n=100;
        bits[] in=new bits[n];

        for (int i=0; i<n; i++) {
            in[i]=new bits(r.nextBoolean()? 1: 0, r.nextInt(N)+1);
        }

        run(in);
    }

    static void run() {
        bits[] in=new bits[] {new bits(0,9),new bits(0,9),new bits(1,2),new bits(1,5), new bits(1,5),new bits(1,8)};
        run(in);
    }

    static void run(bits[] in) {
        long ret1=solve(in);
        long ret2=baseline(in);

        if(ret1!=ret2) {
            System.out.println("expected: "+ret2+" got "+ret1);
            System.out.println(Arrays.deepToString(in));
        } else {
            System.out.println("all good");
        }
    }

    static long baseline(bits[] in) {
        int n=in.length;
        long max=-1, ret=0;
        for (int i=0; i<n; i++) {
            for (int j=i+1; j<n; j++) {
                for (int k=j+1; k<n; k++) {
                    if(h(in[i],in[j],in[k])>max) {
                        max=h(in[i],in[j],in[k]);
                        ret=1;
                        if(DEBUG&&max==20) {
                            System.out.println(i+","+j+","+k);
                        }
                    } else if(h(in[i],in[j],in[k])==max) {
                        ret++;
                        if(DEBUG&&max==20) {
                            System.out.println(i+","+j+","+k);
                        }
                    }
                }
            }
        }

        if(DEBUG) {
            System.out.println("maxh: "+max);
        }
        return ret;
    }
}


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

public class E {

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;
	boolean eof;

	int ansVal = -1;
	long ansCnt = 0;

	void updateAns(int val, long count) {
		if (count == 0) {
			return;
		}
		if (val > ansVal) {
			ansVal = val;
			ansCnt = count;
		} else if (val == ansVal) {
			ansCnt += count;
		}
	}

	static class Group {
		int val;
		int rep;

		public Group(int val, int rep) {
			this.val = val;
			this.rep = rep;
		}
	}

	void solve() throws IOException {
		int n = nextInt();
		int m = nextInt();

		List<Integer> aList = new ArrayList<>();
		List<Integer> bList = new ArrayList<>();

		int na, nb;

		for (int i = 0; i < m; i++) {
			int type = nextInt();
			int val = nextInt();
			(type == 0 ? aList : bList).add(val);
		}

		na = aList.size();
		nb = bList.size();

		Group[] a = makeGroups(aList);
		Group[] b = makeGroups(bList);

		solve1(a, na);
		solve1(b, nb);
		solve2(a, b, n, na, nb);
		solve2(b, a, n, na, nb);

		out.println(ansCnt);
	}

	Group[] makeGroups(List<Integer> a) {
		Collections.sort(a);
		List<Group> b = new ArrayList<>();
		for (int i = 0, j = -1; i < a.size(); i = j) {
			j = i;
			int st = a.get(i);
			while (j < a.size() && a.get(j).intValue() == st) {
				j++;
			}
			b.add(new Group(st, j - i));
		}
		return b.toArray(new Group[b.size()]);
	}

	void solve1(Group[] a, int realLen) {
		if (a.length == 0) {
			return;
		}
		int n = a.length;
		int val = 2 * (a[n - 1].val - a[0].val);
		long count;
		if (a.length == 1) {
			count = (long) realLen * (realLen - 1) * (realLen - 2) / 6;
		} else {
			int pref = a[0].rep;
			int suff = a[n - 1].rep;

			count = (long) pref * (realLen - pref - suff) * suff + (long) pref
					* (pref - 1) / 2 * suff + (long) pref * suff * (suff - 1)
					/ 2;
		}
		updateAns(val, count);
	}

	long C2(int x) {
		return (long) x * (x - 1) / 2;
	}

	void solve2(Group[] a, Group[] b, int n, int realLenA, int realLenB) {
		int na = a.length;
		int nb = b.length;

		if (na == 0 || nb == 0) {
			return;
		}
		// j is last in b <= a[i]

		int totBNotMore = 0;
		int totBMore = realLenB;

		for (int i = 0, j = -1; i < na; i++) {
			while (j < nb - 1 && b[j + 1].val <= a[i].val) {
				j++;
				totBNotMore += b[j].rep;
				totBMore -= b[j].rep;
			}
			// both <=
			if (j >= 0) {
				int val = 2 * (b[j].val + n - a[i].val);
				long count = (long) a[i].rep
						* (C2(totBNotMore) - C2(totBNotMore - b[j].rep));
				updateAns(val, count);
			}

			// <= and >
			if (j >= 0 && j < nb - 1) {
				int val = 2 * n;
				long count = (long) a[i].rep * totBNotMore * totBMore;
				updateAns(val, count);
			}

			// both >
			if (j < nb - 1) {
				// System.err.println("?");
				int val = 2 * (-b[j + 1].val + n + a[i].val);
				long count = (long) a[i].rep
						* (C2(totBMore) - C2(totBMore - b[j + 1].rep));
				updateAns(val, count);
			}
		}
	}

	E() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		out.close();
	}

	public static void main(String[] args) throws IOException {
		new E();
	}

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (Exception e) {
				eof = true;
				return null;
			}
		}
		return st.nextToken();
	}

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			eof = true;
			return null;
		}
	}

	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
}


import java.util.*;
import java.io.*;
import java.math.*;

public class Main {
    public static void main(String args[]) throws Exception {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task solver = new Task();
        solver.main(in, out);
        out.close();
    }
}

class Task {
    final int maxn = 41111;
    ArrayList<Integer> Beg, End;
    Integer[] X, Y;
    int N, M;
    PrintStream cout = System.out;

    void print(Object[] arr) {
        cout.println("print arr :");
        for (Object i : arr) {
            cout.print(i + " ");
        }
        cout.println();
    }

    int value;
    long ans = 0;

    void update(int v, long c) {
        if (v == value) {
            ans += c;
        } else if (v > value) {
            value = v;
            ans = c;
        }
    }

    long calc(long n) {
        n = n * n - n;
        n >>= 1;
        return n;
    }

    long single(Integer[] x) {
        int n = x.length;
        int mi = x[0];
        int ma = x[n - 1];
        int a = 0, b = 0;

        long ans = n;
        if (x[0].equals(x[n - 1])) {
            ans = ans * (ans - 1) * (ans - 2) / 6;

        } else {
            for (int i = 0; i < n; ++i) {
                if (x[i] == x[0])
                    ++a;
                if (x[i] == x[0])
                    ++b;
            }
            ans -= b + a;
            ans = ans * a * b;
            ans += calc(a) * b;
            ans += calc(b) * a;
        }
        return ans;
    }

    void run(Integer x[], Integer y[]) {
        int n = x.length;
        int m = y.length;
        int i, j;
        long sub = 0;
        int c = 0;
        for (i = 0, j = 0; i < n; ++i) {
            while (j < m && y[j] < x[i]) {
                ++j;
                ++c;
            }
            sub += calc(c);
        }
        c = 0;
        for (i = n - 1, j = m - 1; i >= 0; --i) {
            while (j >= 0 && y[j] > x[i]) {
                --j;
                ++c;
            }
            sub += calc(c);
        }
        sub = calc(m) * n - sub;

        update(N * 2, sub);
    }

    void main(InputReader in, PrintWriter out) throws Exception {
        Beg = new ArrayList<Integer>();
        End = new ArrayList<Integer>();
        N = in.nextInt();
        M = in.nextInt();
        for (int i = 0; i < M; ++i) {
            int t, s;
            t = in.nextInt();
            s = in.nextInt();
            if (t == 0) {
                Beg.add(s);
            } else {
                End.add(s);
            }
        }
        // out.println(Beg.size());
        X = Beg.toArray(new Integer[Beg.size()]);
        Y = End.toArray(new Integer[End.size()]);
        Arrays.sort(X);
        Arrays.sort(Y);
        // print(X);
        // print(Y);
        int n = X.length;
        int m = Y.length;
        ans = 0;
        if (m > 2) {
            update(2 * (Y[m - 1] - Y[0]), single(Y));

        }
        if (n > 2) {
            update(2 * (X[n - 1] - X[0]), single(X));

        }
        if (n > 0 && m > 0) {
            if (X[n - 1] < Y[0]) {
                update(N * 2 - (Y[0] - X[n - 1]), m + n - 2);
            } else if (X[0] > Y[m - 1]) {
                update(N * 2 - (X[0] - Y[m - 1]), m + n - 2);
            } else {
                run(X, Y);
                run(Y, X);
            }
        }
        out.println(ans);

    }
}

class InputReader {
    BufferedReader reader;
    StringTokenizer tokenizer;

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

    String next() {
        if (!hasNext())
            throw new RuntimeException();
        return tokenizer.nextToken();
    }

    boolean hasNext() {
        while (tokenizer == null || !tokenizer.hasMoreTokens())
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (Exception e) {
                return false;
            }
        return true;
    }

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

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