import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.PrintStream;
import java.util.Arrays;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 29);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            PrintWriter out = new PrintWriter(outputStream);
            DGraphAndQueries solver = new DGraphAndQueries();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class DGraphAndQueries {
        Debug debug = new Debug(true);

        public void solve(int testNumber, FastInput in, PrintWriter out) {
            int n = in.readInt();
            int m = in.readInt();
            int q = in.readInt();
            int[] p = new int[n];
            in.populate(p);

            Edge[] edges = new Edge[m];
            for (int i = 0; i < m; i++) {
                edges[i] = new Edge();
                edges[i].a = in.readInt() - 1;
                edges[i].b = in.readInt() - 1;
            }

            int[][] qs = new int[4][q];
            for (int i = 0; i < q; i++) {
                for (int j = 0; j < 2; j++) {
                    qs[j][i] = in.readInt();
                }
                if (qs[0][i] == 2) {
                    edges[qs[1][i] - 1].delete = true;
                }
            }

            DSUExt dsu = new DSUExt(n);
            dsu.reset();
            for (Edge e : edges) {
                if (e.delete) {
                    continue;
                }
                dsu.merge(e.a, e.b);
            }

            for (int i = q - 1; i >= 0; i--) {
                if (qs[0][i] == 2) {
                    Edge e = edges[qs[1][i] - 1];
                    dsu.merge(e.a, e.b);
                } else {
                    int v = qs[1][i] - 1;
                    int pa = dsu.find(v);
                    qs[2][i] = dsu.begin[pa];
                    qs[3][i] = dsu.end[pa];
                }
            }

            int[] id = new int[n];
            int[] inv = new int[n];
            int idAlloc = 0;
            for (int i = 0; i < n; i++) {
                if (dsu.find(i) != i) {
                    continue;
                }
                for (int trace = dsu.begin[i]; trace != -1; trace = dsu.next[trace]) {
                    id[trace] = idAlloc++;
                    inv[id[trace]] = trace;
                }
            }

            Segment seg = new Segment(0, n - 1, i -> p[inv[i]]);
            debug.debug("seg", seg);
            for (int i = 0; i < q; i++) {
                if (qs[0][i] != 1) {
                    continue;
                }
                int l = id[qs[2][i]];
                int r = id[qs[3][i]];
                if (l > r) {
                    int tmp = l;
                    l = r;
                    r = tmp;
                }
                int ans = seg.query(l, r, 0, n - 1);
                seg.pop(l, r, 0, n - 1, ans);
                out.println(ans);

                debug.debug("debug", seg);
            }
        }

    }

    static class Segment implements Cloneable {
        private Segment left;
        private Segment right;
        private int max;

        private void modify(int x) {
            max = x;
        }

        public void pushUp() {
            max = Math.max(left.max, right.max);
        }

        public void pushDown() {
        }

        public Segment(int l, int r, IntToIntegerFunction func) {
            if (l < r) {
                int m = DigitUtils.floorAverage(l, r);
                left = new Segment(l, m, func);
                right = new Segment(m + 1, r, func);
                pushUp();
            } else {
                max = func.apply(l);
            }
        }

        private boolean covered(int ll, int rr, int l, int r) {
            return ll <= l && rr >= r;
        }

        private boolean noIntersection(int ll, int rr, int l, int r) {
            return ll > r || rr < l;
        }

        public boolean pop(int ll, int rr, int l, int r, int maxVal) {
            if (noIntersection(ll, rr, l, r)) {
                return false;
            }
            if (covered(ll, rr, l, r)) {
                if (max != maxVal) {
                    return false;
                }
                if (l == r) {
                    modify(0);
                    return true;
                }
            }
            pushDown();
            int m = DigitUtils.floorAverage(l, r);
            boolean ans = left.pop(ll, rr, l, m, maxVal);
            if (!ans) {
                ans = right.pop(ll, rr, m + 1, r, maxVal);
            }
            pushUp();
            return ans;
        }

        public int query(int ll, int rr, int l, int r) {
            if (noIntersection(ll, rr, l, r)) {
                return 0;
            }
            if (covered(ll, rr, l, r)) {
                return max;
            }
            pushDown();
            int m = DigitUtils.floorAverage(l, r);
            return Math.max(left.query(ll, rr, l, m),
                    right.query(ll, rr, m + 1, r));
        }

        private Segment deepClone() {
            Segment seg = clone();
            if (seg.left != null) {
                seg.left = seg.left.deepClone();
            }
            if (seg.right != null) {
                seg.right = seg.right.deepClone();
            }
            return seg;
        }

        protected Segment clone() {
            try {
                return (Segment) super.clone();
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException(e);
            }
        }

        private void toString(StringBuilder builder) {
            if (left == null && right == null) {
                builder.append(max).append(",");
                return;
            }
            pushDown();
            left.toString(builder);
            right.toString(builder);
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            deepClone().toString(builder);
            if (builder.length() > 0) {
                builder.setLength(builder.length() - 1);
            }
            return builder.toString();
        }

    }

    static class Debug {
        private boolean offline;
        private PrintStream out = System.err;
        static int[] empty = new int[0];

        public Debug(boolean enable) {
            offline = enable && System.getSecurityManager() == null;
        }

        public Debug debug(String name, Object x) {
            return debug(name, x, empty);
        }

        public Debug debug(String name, Object x, int... indexes) {
            if (offline) {
                if (x == null || !x.getClass().isArray()) {
                    out.append(name);
                    for (int i : indexes) {
                        out.printf("[%d]", i);
                    }
                    out.append("=").append("" + x);
                    out.println();
                } else {
                    indexes = Arrays.copyOf(indexes, indexes.length + 1);
                    if (x instanceof byte[]) {
                        byte[] arr = (byte[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof short[]) {
                        short[] arr = (short[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof boolean[]) {
                        boolean[] arr = (boolean[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof char[]) {
                        char[] arr = (char[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof int[]) {
                        int[] arr = (int[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof float[]) {
                        float[] arr = (float[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof double[]) {
                        double[] arr = (double[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else if (x instanceof long[]) {
                        long[] arr = (long[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    } else {
                        Object[] arr = (Object[]) x;
                        for (int i = 0; i < arr.length; i++) {
                            indexes[indexes.length - 1] = i;
                            debug(name, arr[i], indexes);
                        }
                    }
                }
            }
            return this;
        }

    }

    static class DSUExt extends DSU {
        int[] begin;
        int[] end;
        int[] next;

        public DSUExt(int n) {
            super(n);
            begin = new int[n];
            end = new int[n];
            next = new int[n];
        }

        public void reset() {
            super.reset();
            for (int i = 0; i < begin.length; i++) {
                begin[i] = end[i] = i;
                next[i] = -1;
            }
        }

        protected void preMerge(int a, int b) {
            next[end[a]] = begin[b];
            end[a] = end[b];
        }

    }

    static interface IntToIntegerFunction {
        int apply(int x);

    }

    static class DigitUtils {
        private DigitUtils() {
        }

        public static int floorAverage(int x, int y) {
            return (x & y) + ((x ^ y) >> 1);
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        public void populate(int[] data) {
            for (int i = 0; i < data.length; i++) {
                data[i] = readInt();
            }
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static class DSU {
        protected int[] p;
        protected int[] rank;

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

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

        public final int find(int a) {
            if (p[a] == p[p[a]]) {
                return p[a];
            }
            preAccess(a);
            return p[a] = find(p[a]);
        }

        protected void preAccess(int a) {

        }

        protected void preMerge(int a, int b) {

        }

        public final void merge(int a, int b) {
            a = find(a);
            b = find(b);
            if (a == b) {
                return;
            }
            if (rank[a] == rank[b]) {
                rank[a]++;
            }

            if (rank[a] < rank[b]) {
                int tmp = a;
                a = b;
                b = tmp;
            }

            preMerge(a, b);
            p[b] = a;
        }

    }

    static class Edge {
        int a;
        int b;
        boolean delete;

    }
}


import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.InputMismatchException;
import java.util.Objects;
import java.util.function.BiFunction;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
	static class TaskAdapter implements Runnable {
		@Override
		public void run() {
			long startTime = System.currentTimeMillis();
			InputStream inputStream = System.in;
			OutputStream outputStream = System.out;
			FastReader in = new FastReader(inputStream);
			Output out = new Output(outputStream);
			DGraphAndQueries solver = new DGraphAndQueries();
			solver.solve(1, in, out);
			out.close();
			System.err.println(System.currentTimeMillis()-startTime+"ms");
		}
	}

	public static void main(String[] args) throws Exception {
		Thread thread = new Thread(null, new TaskAdapter(), "", 1<<28);
		thread.start();
		thread.join();
	}

	static class DGraphAndQueries {
		int[] arr;
		int[] parent;
		int[] tin;
		int[] tout;
		int n;
		int ind;
		int clock;
		BitSet visited;
		Pair<Integer, Integer>[] tour;
		ArrayList<Integer>[] graph;

		public DGraphAndQueries() {
		}

		public int find(int u) {
			return parent[u]==u ? u : (parent[u] = find(parent[u]));
		}

		public void merge(Pair<Integer, Integer> p) {
			int u = find(p.a), v = find(p.b);
			if(u==v) {
				return;
			}
			int next = ind++;
			parent[u] = parent[v] = next;
			graph[next] = new ArrayList<>(Arrays.asList(u, v));
		}

		public void dfs(int u) {
			tour[clock] = new Pair<>(arr[u], tin[u] = clock++);
			if(u>=n) {
				for(int v: graph[u]) {
					dfs(v);
				}
			}
			tout[u] = clock-1;
		}

		public void solve(int kase, InputReader in, Output pw) {
			n = in.nextInt();
			int m = in.nextInt(), q = in.nextInt();
			arr = new int[n+q];
			Arrays.fill(arr, -1);
			parent = new int[n+q];
			graph = new ArrayList[n+q];
			ind = n;
			for(int i = 0; i<n; i++) {
				arr[i] = in.nextInt();
			}
			for(int i = 0; i<n+q; i++) {
				parent[i] = i;
			}
			Pair<Integer, Integer>[] edges = new Pair[m];
			for(int i = 0; i<m; i++) {
				edges[i] = new Pair<>(in.nextInt()-1, in.nextInt()-1);
			}
			BitSet marked = new BitSet(m);
			int[][] queries = new int[q][2];
			for(int i = 0; i<q; i++) {
				queries[i] = new int[] {in.nextInt(), in.nextInt()-1};
				if(queries[i][0]==2) {
					marked.set(queries[i][1]);
				}
			}
			for(int i = 0; i<m; i++) {
				if(!marked.get(i)) {
					merge(edges[i]);
				}
			}
			for(int i = q-1; i>=0; i--) {
				if(queries[i][0]==2) {
					merge(edges[queries[i][1]]);
				}else {
					queries[i][1] = find(queries[i][1]);
				}
			}
			Utilities.Debug.dbg(ind);
			Utilities.Debug.dbg(graph);
			tour = new Pair[ind];
			tin = new int[ind];
			tout = new int[ind];
			visited = new BitSet(ind);
			clock = 0;
			for(int i = 0; i<n; i++) {
				int u = find(i);
				if(!visited.get(u)) {
					dfs(u);
					visited.set(u);
				}
			}
			Utilities.Debug.dbg(tour);
			TPointSegmentTree<Pair<Integer, Integer>> st = new TPointSegmentTree<>(tour, (o1, o2) -> o1.a>=o2.a ? o1 : o2);
			for(int[] query: queries) {
				if(query[0]==1) {
					int u = query[1];
					var v = st.query(tin[u], tout[u]);
					Utilities.Debug.dbg(u, v);
					pw.println(v.a);
					st.set(v.b, new Pair<>(0, v.b));
				}
			}
		}

	}

	static class TPointSegmentTree<T> {
		public int n;
		public int ind;
		public int ql;
		public int qr;
		public T[] arr;
		public T[] value;
		public BiFunction<T, T, T> operation;

		public TPointSegmentTree(T[] arr, BiFunction<T, T, T> operation) {
			n = arr.length;
			this.arr = arr;
			value = (T[]) new Object[n<<2];
			this.operation = operation;
			build(1, 0, n-1);
		}

		private void build(int o, int l, int r) {
			if(l==r) {
				value[o] = arr[l];
				return;
			}
			int lc = o<<1, rc = lc|1, mid = l+r >> 1;
			build(lc, l, mid);
			build(rc, mid+1, r);
			value[o] = operation.apply(value[lc], value[rc]);
		}

		private void set(int o, int l, int r) {
			if(l==r) {
				value[o] = arr[l];
				return;
			}
			int lc = o<<1, rc = lc|1, mid = l+r >> 1;
			if(ind<=mid) {
				set(lc, l, mid);
			}else {
				set(rc, mid+1, r);
			}
			value[o] = operation.apply(value[lc], value[rc]);
		}

		public void set(int ind, T val) {
			this.ind = ind;
			arr[ind] = val;
			set(1, 0, n-1);
		}

		private T query(int o, int l, int r) {
			if(ql<=l&&qr>=r) {
				return value[o];
			}
			int lc = o<<1, rc = lc|1, mid = l+r >> 1;
			T ret = null;
			if(ql<=mid) {
				ret = query(lc, l, mid);
			}
			if(qr>mid) {
				if(ret==null) {
					ret = query(rc, mid+1, r);
				}else {
					ret = operation.apply(ret, query(rc, mid+1, r));
				}
			}
			return ret;
		}

		public T query(int l, int r) {
			ql = l;
			qr = r;
			return query(1, 0, n-1);
		}

	}

	static class Utilities {
		public static class Debug {
			public static final boolean LOCAL = System.getProperty("ONLINE_JUDGE")==null;

			private static <T> String ts(T t) {
				if(t==null) {
					return "null";
				}
				try {
					return ts((Iterable) t);
				}catch(ClassCastException e) {
					if(t instanceof int[]) {
						String s = Arrays.toString((int[]) t);
						return "{"+s.substring(1, s.length()-1)+"}";
					}else if(t instanceof long[]) {
						String s = Arrays.toString((long[]) t);
						return "{"+s.substring(1, s.length()-1)+"}";
					}else if(t instanceof char[]) {
						String s = Arrays.toString((char[]) t);
						return "{"+s.substring(1, s.length()-1)+"}";
					}else if(t instanceof double[]) {
						String s = Arrays.toString((double[]) t);
						return "{"+s.substring(1, s.length()-1)+"}";
					}else if(t instanceof boolean[]) {
						String s = Arrays.toString((boolean[]) t);
						return "{"+s.substring(1, s.length()-1)+"}";
					}
					try {
						return ts((Object[]) t);
					}catch(ClassCastException e1) {
						return t.toString();
					}
				}
			}

			private static <T> String ts(T[] arr) {
				StringBuilder ret = new StringBuilder();
				ret.append("{");
				boolean first = true;
				for(T t: arr) {
					if(!first) {
						ret.append(", ");
					}
					first = false;
					ret.append(ts(t));
				}
				ret.append("}");
				return ret.toString();
			}

			private static <T> String ts(Iterable<T> iter) {
				StringBuilder ret = new StringBuilder();
				ret.append("{");
				boolean first = true;
				for(T t: iter) {
					if(!first) {
						ret.append(", ");
					}
					first = false;
					ret.append(ts(t));
				}
				ret.append("}");
				return ret.toString();
			}

			public static void dbg(Object... o) {
				if(LOCAL) {
					System.err.print("Line #"+Thread.currentThread().getStackTrace()[2].getLineNumber()+": [");
					for(int i = 0; i<o.length; i++) {
						if(i!=0) {
							System.err.print(", ");
						}
						System.err.print(ts(o[i]));
					}
					System.err.println("]");
				}
			}

		}

	}

	static class Output implements Closeable, Flushable {
		public StringBuilder sb;
		public OutputStream os;
		public int BUFFER_SIZE;
		public String lineSeparator;

		public Output(OutputStream os) {
			this(os, 1<<16);
		}

		public Output(OutputStream os, int bs) {
			BUFFER_SIZE = bs;
			sb = new StringBuilder(BUFFER_SIZE);
			this.os = new BufferedOutputStream(os, 1<<17);
			lineSeparator = System.lineSeparator();
		}

		public void println(int i) {
			println(String.valueOf(i));
		}

		public void println(String s) {
			sb.append(s);
			println();
		}

		public void println() {
			sb.append(lineSeparator);
		}

		private void flushToBuffer() {
			try {
				os.write(sb.toString().getBytes());
			}catch(IOException e) {
				e.printStackTrace();
			}
			sb = new StringBuilder(BUFFER_SIZE);
		}

		public void flush() {
			try {
				flushToBuffer();
				os.flush();
			}catch(IOException e) {
				e.printStackTrace();
			}
		}

		public void close() {
			flush();
			try {
				os.close();
			}catch(IOException e) {
				e.printStackTrace();
			}
		}

	}

	static interface InputReader {
		int nextInt();

	}

	static class Pair<T1, T2> implements Comparable<Pair<T1, T2>> {
		public T1 a;
		public T2 b;

		public Pair(Pair<T1, T2> p) {
			this(p.a, p.b);
		}

		public Pair(T1 a, T2 b) {
			this.a = a;
			this.b = b;
		}

		public String toString() {
			return a+" "+b;
		}

		public int hashCode() {
			return Objects.hash(a, b);
		}

		public boolean equals(Object o) {
			if(o instanceof Pair) {
				Pair p = (Pair) o;
				return a.equals(p.a)&&b.equals(p.b);
			}
			return false;
		}

		public int compareTo(Pair<T1, T2> p) {
			int cmp = ((Comparable<T1>) a).compareTo(p.a);
			if(cmp==0) {
				return ((Comparable<T2>) b).compareTo(p.b);
			}
			return cmp;
		}

	}

	static class FastReader implements InputReader {
		final private int BUFFER_SIZE = 1<<16;
		private DataInputStream din;
		private byte[] buffer;
		private int bufferPointer;
		private int bytesRead;

		public FastReader(InputStream is) {
			din = new DataInputStream(is);
			buffer = new byte[BUFFER_SIZE];
			bufferPointer = bytesRead = 0;
		}

		public int nextInt() {
			int ret = 0;
			byte c = skipToDigit();
			boolean neg = (c=='-');
			if(neg) {
				c = read();
			}
			do {
				ret = ret*10+c-'0';
			} while((c = read())>='0'&&c<='9');
			if(neg) {
				return -ret;
			}
			return ret;
		}

		private boolean isDigit(byte b) {
			return b>='0'&&b<='9';
		}

		private byte skipToDigit() {
			byte ret;
			while(!isDigit(ret = read())&&ret!='-') ;
			return ret;
		}

		private void fillBuffer() {
			try {
				bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
			}catch(IOException e) {
				e.printStackTrace();
				throw new InputMismatchException();
			}
			if(bytesRead==-1) {
				buffer[0] = -1;
			}
		}

		private byte read() {
			if(bytesRead==-1) {
				throw new InputMismatchException();
			}else if(bufferPointer==bytesRead) {
				fillBuffer();
			}
			return buffer[bufferPointer++];
		}

	}
}


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;
		PriorityQueue<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 PriorityQueue[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 PriorityQueue<>();
				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;
			}
			p[pa] = pa;
			sz[pb] -= sz[pa];
		}

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

	int[] inv;

	public void solve() {
		int n = in.nextInt();
		int m = in.nextInt();
		int q = in.nextInt();
		int[] v = new int[n];
		inv = new int[n];
		for (int i = 0; i < v.length; i++) {
			v[i] = in.nextInt();
			inv[v[i] - 1] = i;
		}
		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<>();
            subtree[i].add(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;
        }
    }
}


//package round673;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class D {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni(), Q = ni();
		int[] a = na(n);
		int[] from = new int[m];
		int[] to = new int[m];
		boolean[] remain = new boolean[m];
		for(int i = 0;i < m;i++) {
			from[i] = ni()-1;
			to[i] = ni()-1;
		}
		Arrays.fill(remain, true);

		int[][] qs = new int[Q][];
		for(int i = 0;i < Q;i++) {
			qs[i] = new int[] {ni(), ni()-1};
			if(qs[i][0] == 2) {
				remain[qs[i][1]] = false;
			}
		}

		int gen = n;
		int[] par = new int[2*n];
		Arrays.fill(par, -1);
		DJSet ds = new DJSet(n);
		for(int i = 0;i < m;i++) {
			if(remain[i]) {
				if(!ds.equiv(from[i], to[i])) {
					int f = ds.tr[ds.root(from[i])];
					int t = ds.tr[ds.root(to[i])];
					ds.union(from[i], to[i]);
					par[f] = gen;
					par[t] = gen;
					ds.tr[ds.root(from[i])] = gen;
					gen++;
				}
			}
		}

		int[] time = new int[2*n];
		Arrays.fill(time, Q);
		for(int i = Q-1;i >= 0;i--) {
			if(qs[i][0] == 2) {
				int ind = qs[i][1];
				if(!ds.equiv(from[ind], to[ind])) {
					int f = ds.tr[ds.root(from[ind])];
					int t = ds.tr[ds.root(to[ind])];
					ds.union(from[ind], to[ind]);
					par[f] = gen;
					par[t] = gen;
					ds.tr[ds.root(from[ind])] = gen;
					time[gen] = i;
					gen++;
				}
			}
		}

		time[2*n-1] = -1;
		for(int i = 0;i < 2*n-1;i++) {
			if(par[i] == -1) {
				par[i] = 2*n-1;
			}
		}

		int[][] g = parentToG(par);
		int[][] rights = makeRights(g, par, 2*n-1);
		int[] iord = rights[1], right = rights[2];
		int[][] spar = logstepParents(par);

		int[] b = new int[2*n];
		for(int i = 0;i < n;i++) {
			b[iord[i]] = -a[i];
		}
		SegmentTreeRMQPos st = new SegmentTreeRMQPos(b);
		for(int i = 0;i < Q;i++) {
			int[] q = qs[i];
			if(q[0] == 1) {
				int v = q[1];
				for(int d = spar.length-1;d >= 0;d--) {
					int anc = spar[d][v];
					if(anc == -1)continue;
					if(time[anc] < i)continue;
					v = anc;
				}
				int[] vp = st.min(iord[v], right[iord[v]]);
				out.println(-vp[0]);
				st.update(vp[1], 0);
			}
		}
	}

	public static class SegmentTreeRMQPos {
		public int M, H, N, B;
		public int[] st;
		public int[] pos;

		public SegmentTreeRMQPos(int n)
		{
			N = n;
			M = Integer.highestOneBit(Math.max(n, 1))<<2;
			H = M>>>1;
			B = Integer.numberOfTrailingZeros(H);
			st = new int[M];
			pos = new int[M];
			for(int i = M-1;i >= H;i--)pos[i] = i-H;
			for(int i = H-1;i >= 0;i--){
				pos[i] = pos[2*i];
			}
		}

		public SegmentTreeRMQPos(int[] a)
		{
			N = a.length;
			M = Integer.highestOneBit(Math.max(N, 1))<<2;
			H = M>>>1;
			B = Integer.numberOfTrailingZeros(H);
			st = new int[M];
			pos = new int[M];
			for(int i = 0;i < N;i++){
				st[H+i] = a[i];
				pos[H+i] = i;
			}
			Arrays.fill(st, H+N, M, Integer.MAX_VALUE);
			for(int i = (M>>1)-1;i >= 1;i--)propagate(i);
		}

		public void update(int p, int x)
		{
			st[H+p] = x;
			for(int i = (H+p)>>>1;i >= 1;i >>>= 1)propagate(i);
		}

		private void propagate(int i)
		{
			if(st[i*2] <= st[i*2+1]){
				st[i] = st[i*2];
				pos[i] = pos[i*2];
			}else{
				st[i] = st[i*2+1];
				pos[i] = pos[i*2+1];
			}
		}

		public int[] min(int f, int t) { return min(f, t, B); }

		public int[] min(int f, int t, int b)
		{
			if(f>>b<<b==f && t+1>>b<<b==t+1){
				return new int[]{st[(H|f)>>b], pos[(H|f)>>b]};
			}

			b--;
			if((f^t)<<31-b<0){
				int w = t>>b<<b;
				int[] l = min(f, w-1, b);
				int[] r = min(w, t, b);
				return l[0] <= r[0] ? l : r;
			}else{
				return min(f, t, b);
			}
		}
	}

	public static int[] sortByPreorder(int[][] g, int root){
		int n = g.length;
		int[] stack = new int[n];
		int[] ord = new int[n];
		boolean[] ved = new boolean[n];
		stack[0] = root;
		int p = 1;
		int r = 0;
		ved[root] = true;
		while(p > 0){
			int cur = stack[p-1];
			ord[r++] = cur;
			p--;
			for(int e : g[cur]){
				if(!ved[e]){
					ved[e] = true;
					stack[p++] = e;
				}
			}
		}
		return ord;
	}

	public static int[][] makeRights(int[][] g, int[] par, int root)
	{
		int n = g.length;
		int[] ord = sortByPreorder(g, root);
		int[] iord = new int[n];
		for(int i = 0;i < n;i++)iord[ord[i]] = i;

		int[] right = new int[n];
		for(int i = n-1;i >= 1;i--){
			if(right[i] == 0)right[i] = i;
			int p = iord[par[ord[i]]];
			right[p] = Math.max(right[p], right[i]);
		}
		return new int[][]{ord, iord, right};
	}

	public static int lca2(int a, int b, int[][] spar, int[] depth) {
		if (depth[a] < depth[b]) {
			b = ancestor(b, depth[b] - depth[a], spar);
		} else if (depth[a] > depth[b]) {
			a = ancestor(a, depth[a] - depth[b], spar);
		}

		if (a == b)
			return a;
		int sa = a, sb = b;
		for (int low = 0, high = depth[a], t = Integer.highestOneBit(high), k = Integer
				.numberOfTrailingZeros(t); t > 0; t >>>= 1, k--) {
			if ((low ^ high) >= t) {
				if (spar[k][sa] != spar[k][sb]) {
					low |= t;
					sa = spar[k][sa];
					sb = spar[k][sb];
				} else {
					high = low | t - 1;
				}
			}
		}
		return spar[0][sa];
	}

	protected static int ancestor(int a, int m, int[][] spar) {
		for (int i = 0; m > 0 && a != -1; m >>>= 1, i++) {
			if ((m & 1) == 1)
				a = spar[i][a];
		}
		return a;
	}

	public static int[][] logstepParents(int[] par) {
		int n = par.length;
		int m = Integer.numberOfTrailingZeros(Integer.highestOneBit(n - 1)) + 1;
		int[][] pars = new int[m][n];
		pars[0] = par;
		for (int j = 1; j < m; j++) {
			for (int i = 0; i < n; i++) {
				pars[j][i] = pars[j - 1][i] == -1 ? -1 : pars[j - 1][pars[j - 1][i]];
			}
		}
		return pars;
	}

	public static int[][] parentToG(int[] par)
	{
		int n = par.length;
		int[] ct = new int[n];
		for(int i = 0;i < n;i++){
			if(par[i] >= 0){
				ct[i]++;
				ct[par[i]]++;
			}
		}
		int[][] g = new int[n][];
		for(int i = 0;i < n;i++){
			g[i] = new int[ct[i]];
		}
		for(int i = 0;i < n;i++){
			if(par[i] >= 0){
				g[par[i]][--ct[par[i]]] = i;
				g[i][--ct[i]] = par[i];
			}
		}
		return g;
	}

	public static class DJSet {
		public int[] upper;
		public int[] tr;

		public DJSet(int n) {
			upper = new int[n];
			Arrays.fill(upper, -1);
			tr = new int[n];
			for(int i = 0;i < n;i++) tr[i] = i;
		}

		public int root(int x) {
			return upper[x] < 0 ? x : (upper[x] = root(upper[x]));
		}

		public boolean equiv(int x, int y) {
			return root(x) == root(y);
		}

		public boolean union(int x, int y) {
			x = root(x);
			y = root(y);
			if (x != y) {
				if (upper[y] < upper[x]) {
					int d = x;
					x = y;
					y = d;
				}
				upper[x] += upper[y];
				upper[y] = x;
			}
			return x == y;
		}

		public int count() {
			int ct = 0;
			for (int u : upper)
				if (u < 0)
					ct++;
			return ct;
		}
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new D().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


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 final int N = 400_004;

    static int n, m, q, timer;
    static int[] p, par, tin, tout, pos;
    static Edge[] edges;
    static Query[] queries;
    static int[][] sons;
    static ArrayList<Integer> order;

    static class Edge {
        int u, v;
        boolean unstable;

        Edge(int u, int v) {
            this.u = u;
            this.v = v;
        }
    }

    static class Query {
        int type, x;
        int leader; // if type = 1

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

    static class SegTree {
        int[] t;
        int size;

        void build(int u, int tl, int tr, ArrayList<Integer> al) {
            if (tl == tr) {
                t[u] = al.get(tl);
            } else {
                int tm = (tl + tr) / 2;
                build(u * 2 + 1, tl, tm, al);
                build(u * 2 + 2, tm + 1, tr, al);
                t[u] = Math.max(t[u * 2 + 1], t[u * 2 + 2]);
            }
        }
        int maxOn(int u, int tl, int tr, int l, int r) {
            if (r < tl || tr < l)
                return -oo;
            if (l <= tl && tr <= r)
                return t[u];
            int tm = (tl + tr) / 2;
            return Math.max(maxOn(u * 2 + 1, tl, tm, l, r), maxOn(u * 2 + 2, tm + 1, tr, l, r));
        }
        void setIn(int u, int tl, int tr, int i, int val) {
            if (tl == tr) {
                t[u] = val;
            } else {
                int tm = (tl + tr) / 2;
                if (i <= tm) {
                    setIn(u * 2 + 1, tl, tm, i, val);
                } else {
                    setIn(u * 2 + 2, tm + 1, tr, i, val);
                }
                t[u] = Math.max(t[u * 2 + 1], t[u * 2 + 2]);
            }
        }

        void build(ArrayList<Integer> al) {
            size = al.size();
            t = new int[size * 4];
            build(0, 0, size - 1, al);
        }
        int maxOn(int l, int r) {
            return maxOn(0, 0, size - 1, l, r);
        }
        void setIn(int i, int val) {
            setIn(0, 0, size - 1, i, val);
        }
    }

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

    static void uniteSets(int u, int v) {
        u = findSet(u);
        v = findSet(v);
        if (u != v) {
            int parent = n++;
            sons[parent][0] = u;
            sons[parent][1] = v;
            par[parent] = parent;
            par[u] = parent;
            par[v] = parent;
        }
    }

    static void dfs(int u) {
        order.add(p[u]);
        if (p[u] != 0)
            pos[p[u]] = timer;
        tin[u] = timer++;
        for (int i = 0; i < 2; i++) {
            if (sons[u][i] != -1)
                dfs(sons[u][i]);
        }
        tout[u] = timer;
    }

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

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

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

        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].unstable = true;
        }

        par = new int[N]; Arrays.fill(par, -1);
        sons = new int[N][2];
        for (int i = 0; i < n; i++) {
            par[i] = i;
            sons[i][0] = sons[i][1] = -1;
        }

        for (Edge e : edges) {
            if (!e.unstable)
                uniteSets(e.u, e.v);
        }
        for (int i = q - 1; i >= 0; i--) {
            Query query = queries[i];
            if (query.type == 1) {
                int u = query.x;
                query.leader = findSet(u);
            } else {
                Edge e = edges[query.x];
                uniteSets(e.u, e.v);
            }
        }
        for (int u = 1; u < n; u++) {
            uniteSets(0, u);
        }
        int root = findSet(0);

        tin = new int[N];
        tout = new int[N];
        order = new ArrayList<>();
        pos = new int[N];
        timer = 0;
        dfs(root);

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

        for (int i = 0; i < q; i++) {
            Query query = queries[i];
            if (query.type == 1) {
                int u = query.leader;
                int maxP = st.maxOn(tin[u], tout[u] - 1);
                out.println(maxP);
                if (maxP != 0)
                    st.setIn(pos[maxP], 0);
            }
        }

    }

    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.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.util.*;

public class E_New_Game_Plus {
    private static final FastReader fs = new FastReader();
    private static final PrintWriter out = new PrintWriter(System.out);

    private static void solve() {
        int n = fs.nextInt(),k = fs.nextInt();
        long[] boss = fs.readlongarray(n);
        rSort(boss);
        PriorityQueue<Long> pq = new PriorityQueue<>(Collections.reverseOrder());
        for(int i = 0; i<k+1; i++) {
        	pq.add(0*1l);
        }
        long ans = 0;
        for(int i = 0; i<n; i++) {
        	long x = pq.remove();
        	ans += x;
        	pq.add(x+boss[i]);
        }
        out.println(ans);
    }

    private static void rSort(long[]a){
        ArrayList<Long> tmp = new ArrayList<>();
        for(long x : a)
            tmp.add(x);
        Collections.sort(tmp);
        Collections.reverse(tmp);
        for(int i = 0; i<tmp.size(); i++)
            a[i] = tmp.get(i);
    }

    public static void main(String[] args) {
        Thread t = new Thread(null, null, "", 1 << 28) {
            public void run() {
                int test_case = 1;
                //test_case = fs.nextInt();
                for (int cs = 1; cs <= test_case; cs++) {
                    solve();
                }
                out.close();
            }
        };
        t.start();
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                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());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        int[] readintarray(int n) {
            int res[] = new int[n];
            for (int i = 0; i < n; i++)
                res[i] = nextInt();
            return res;
        }

        long[] readlongarray(int n) {
            long res[] = new long[n];
            for (int i = 0; i < n; i++)
                res[i] = nextLong();
            return res;
        }
    }

    private static class cf {
        public static int min(int x, int y) {
            return Math.min(x, y);
        }

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

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

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

        public static int abs(int x) {
            return x >= 0 ? x : -x;
        }

        public static long abs(long x) {
            return x >= 0 ? x : -x;
        }

        public static boolean even(int x) {
            return x % 2 == 0 ? true : false;
        }

        public static boolean even(long x) {
            return x % 2 == 0 ? true : false;
        }

        public static int power(int base, int exponent) {
            int res = 1;
            while (exponent > 0) {
                if (!even(exponent))
                    res *= base;
                exponent >>= 1;
                base *= base;
            }
            return res;
        }

        public static long power(long base, long exponent) {
            long res = 1;
            while (exponent > 0) {
                if (!even(exponent))
                    res *= base;
                exponent >>= 1;
                base *= base;
            }
            return res;
        }

        public static long mul(long a, long b, long mod) {
            return (a % mod * b % mod) % mod;
        }

        public static long add(long a, long b, long mod) {
            return (a % mod + b % mod) % mod;
        }

        public static long sub(long a, long b, long mod) {
            return ((a % mod - b % mod) % mod + mod) % mod;
        }

        public static long power(long base, long exponent, long mod) {
            long res = 1;
            base %= mod;
            while (exponent > 0) {
                if (!even(exponent))
                    res = mul(res, base, mod);
                exponent >>= 1;
                base = mul(base, base, mod);
            }
            return res;
        }
    }
}


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

public class E {

    public static void main(String[] args) {
        FastReader scan = new FastReader();
        PrintWriter out = new PrintWriter(System.out);
        Task solver = new Task();
        int t = 1;
        for(int tt = 1; tt <= t; tt++) solver.solve(tt, scan, out);
        out.close();
    }

    static class Task {
        public void solve(int testNumber, FastReader scan, PrintWriter out) {
            int n = scan.nextInt(), k = scan.nextInt();
            PriorityQueue<Long> queue = new PriorityQueue<>(Collections.reverseOrder());
            long ans = 0;
            long[] a = new long[n];
            for(int i = 0; i < n; i++) a[i] = scan.nextLong();
            ruffleSort(a);
            for(int i = 0; i <= k; i++) queue.add(0L);
            for(int i = n - 1; i >= 0; i--) {
                long curr = queue.poll();
                ans += curr;
                queue.add(curr + a[i]);
            }
            out.println(ans);
        }
    }

    static void ruffleSort(int[] a) {
        Random get = new Random();
        for (int i = 0; i < a.length; i++) {
            int r = get.nextInt(a.length);
            int temp = a[i];
            a[i] = a[r];
            a[r] = temp;
        }
        Arrays.sort(a);
    }

    static void ruffleSort(long[] a) {
        Random get = new Random();
        for (int i = 0; i < a.length; i++) {
            int r = get.nextInt(a.length);
            long temp = a[i];
            a[i] = a[r];
            a[r] = temp;
        }
        Arrays.sort(a);
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public FastReader(String s) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(new File(s)));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                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());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }

}


import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.NoSuchElementException;
import java.io.Writer;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskD {
	static final long MOD = 1000000007;

	public void solve(int testNumber, InputReader in, OutputWriter out) {
		int rowCount = in.readInt();
		int columnCount = in.readInt();
		long[][] strict = new long[rowCount][columnCount];
		long[][] nonStrict = new long[rowCount][columnCount];
		Arrays.fill(strict[0], 1, columnCount, 1);
		Arrays.fill(nonStrict[0], 1, columnCount, 1);
		for (int i = 1; i < rowCount; i++) {
			long sum = 0;
			long result = 0;
			for (int j = 0; j < columnCount; j++) {
				result += sum;
				if (result >= MOD)
					result -= MOD;
				strict[i][j] = result;
				result += nonStrict[i - 1][j];
				sum += nonStrict[i - 1][j];
				if (result >= MOD)
					result -= MOD;
				if (sum >= MOD)
					sum -= MOD;
				nonStrict[i][j] = result;
			}
		}
		long answer = 0;
		for (int i = 0; i < columnCount; i++) {
			long sum = 0;
			long result = 0;
			long current = 0;
			for (int j = 0; j < rowCount; j++) {
				sum += nonStrict[j][i];
				if (sum >= MOD)
					sum -= MOD;
				result += sum;
				if (result >= MOD)
					result -= MOD;
				current += strict[rowCount - j - 1][i] * result % MOD;
			}
			current %= MOD;
			answer += current * (columnCount - i);
		}
		answer %= MOD;
		out.printLine(answer);
    }
}

class InputReader {

	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

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

	public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return isWhitespace(c);
	}

	public static boolean isWhitespace(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}
}

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
	}

	public OutputWriter(Writer writer) {
		this.writer = new PrintWriter(writer);
	}

	public void print(Object...objects) {
		for (int i = 0; i < objects.length; i++) {
			if (i != 0)
				writer.print(' ');
			writer.print(objects[i]);
		}
	}

    public void printLine(Object...objects) {
		print(objects);
		writer.println();
	}

	public void close() {
		writer.close();
	}

	}


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

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author AlexFetisov
 */
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);
		TaskD_EgorAndCaves solver = new TaskD_EgorAndCaves();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD_EgorAndCaves {
    public static final int MOD = (int)1e9 + 7;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int m = in.nextInt();

        if (m < 2) {
            out.println(0);
            return;
        }
        long[][] dp = new long[n+1][m+1];
        long[][] lastRow = new long[n+1][m+1];

        for (int width = 2; width <= m; ++width) {
            dp[0][width] = 1;
        }
        long[] sum = new long[m+1];
        long[] sum2 = new long[m+1];
        for (int row = 1; row < n; ++row) {
            sum[0] = sum[1] = 0;
            sum2[0] = sum2[1] = 0;
            for (int i = 2; i <= m; ++i) {
                sum[i] = sum[i-1] + dp[row-1][i];
                if (sum[i] >= MOD) sum[i] -= MOD;
                sum2[i] = sum2[i-1] + (dp[row-1][i] * i) % MOD;
                if (sum2[i] >= MOD) sum2[i] -= MOD;
            }
            for (int width = 2; width <= m; ++width) {
                dp[row][width] = 1;
                lastRow[row][width] = 0;
                dp[row][width] += ((width + 1) * sum[width]) % MOD;
                if (dp[row][width] >= MOD) {
                    dp[row][width] -= MOD;
                }
                dp[row][width] -= sum2[width];
                if (dp[row][width] < 0) {
                    dp[row][width] += MOD;
                }
                lastRow[row][width] += ((width + 1) * sum[width-1]) % MOD;
                if (lastRow[row][width] >= MOD) {
                    lastRow[row][width] -= MOD;
                }
                lastRow[row][width] -= sum2[width-1];
                if (lastRow[row][width] < 0) {
                    lastRow[row][width] += MOD;
                }
            }
        }

        long res = 0;
        for (int t = 0; t < n; ++t) {
            for (int width = 2; width <= m; ++width) {
                res += ((dp[t][width]) % MOD) * (m - width + 1) % MOD;
                if (res >= MOD) {
                    res -= MOD;
                }
                res += ((dp[t][width] * lastRow[n - t - 1][width]) % MOD) * (m - width + 1) % MOD;
                if (res >= MOD) {
                    res -= MOD;
                }
            }
        }
        out.println(res);
    }
}

class InputReader {
    private BufferedReader reader;
    private StringTokenizer stt;

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

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

    public String nextString() {
        while (stt == null || !stt.hasMoreTokens()) {
            stt = new StringTokenizer(nextLine());
        }
        return stt.nextToken();
    }

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

}


import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.StringTokenizer;
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;
        Parser in = new Parser(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }
}

class TaskD {
    int mod = 1000000007;
    long[][] sum1d = new long[3000][3000];
    long[][] sum2d = new long[3000][3000];

    public void solve(int testNumber, Parser in, OutputWriter out) {
        int n = in.nextInt();
        int m = in.nextInt();

        for (int rows = 0; rows <= n; rows++) {
            for (int i = 2; i <= m; i++) {
                sum1d[rows][i] = (rows==0) ? 1 : sum2d[rows-1][i]+1;
                if (i != 0) sum1d[rows][i] = (sum1d[rows][i] + sum1d[rows][i-1]) % mod;

                sum2d[rows][i] = sum1d[rows][i];
                if (i != 0) sum2d[rows][i] = (sum2d[rows][i] + sum2d[rows][i-1]) % mod;
            }
        }

        long tot = 0;
        for (int i = 0; i < n; i++) {
            for (int mid = 2; mid <= m; mid++) {
                // res=(res+(((((pd[w][t][1]-pd[w][t-1][1]+M)%M)*pd[w][n-t+1][1])%M)*(m-w+1))%M)%M;
                long top = (i==0) ? 1 : (sum2d[i-1][mid-1]+sum1d[i-1][mid-1]+1);
                long bot = (n-i-1==0) ? 1 : sum2d[n-i-2][mid]+1;

                bot = (bot * top) % mod;
                bot = (bot * (m-mid+1)) % mod;
                tot = (tot + bot) % mod;
            }
        }

        out.println(tot);
    }
}

class Parser
{
    private BufferedReader din;
    private StringTokenizer tokenizer;

    public Parser(InputStream in)
    {
        din = new BufferedReader(new InputStreamReader(in));
        tokenizer = null;
    }

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

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

    }

class OutputWriter extends PrintWriter {
    public OutputWriter(Writer out) {
        super(out);
    }

    public OutputWriter(OutputStream out) {
        super(out);
    }

    }


import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.io.PrintStream;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.io.Reader;
import java.io.Writer;
import java.io.InputStream;

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

class TaskD {

    public void solve(int testNumber, FastScanner in, FastPrinter out) {
//        test();
        int n = in.nextInt();
        int m = in.nextInt();
        out.println(solve(n, m));
//        if (solve(n, m) != solveStupid(n, m)) {
//            throw new AssertionError();
//        }
    }

    static final int MOD = 1000000007;

    static int solve(int n, int m) {
        int[][] dp = new int[m][n + 1];
        int[][] dp2 = new int[m][n + 1];
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            int s = 0;
            int ss = 0;
            dp[0][i] = 1;
            for (int j = 1; j < m; j++) {
                dp2[j][i] = (ss + s + 1) % MOD;
                s += dp[j][i - 1];
                if (s >= MOD) {
                    s -= MOD;
                }
                ss += s;
                if (ss >= MOD) {
                    ss -= MOD;
                }
                dp[j][i] = (ss + 1) % MOD;
            }
        }
        int ans = 0;
        for (int i = 0; i < n; i++) {
            int cur = 0;
            for (int j = 1; j < m; j++) {
                cur = (int) ((cur + (long) dp[j][i + 1] * dp2[j][n - i] % MOD * (m - j)) % MOD);
            }
            ans += cur;
            if (ans >= MOD) {
                ans -= MOD;
            }
        }
        return ans;
    }

    }

class FastScanner extends BufferedReader {

    boolean isEOF;

    public FastScanner(InputStream is) {
        super(new InputStreamReader(is));
    }

    public int read() {
        try {
            int ret = super.read();
            if (isEOF && ret < 0) {
                throw new InputMismatchException();
            }
            isEOF = ret == -1;
            return ret;
        } catch (IOException e) {
            throw new InputMismatchException();
        }
    }

    static boolean isWhiteSpace(int c) {
        return c >= 0 && c <= 32;
    }

    public int nextInt() {
        int c = read();
        while (isWhiteSpace(c)) {
            c = read();
        }
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int ret = 0;
        while (c >= 0 && !isWhiteSpace(c)) {
            if (c < '0' || c > '9') {
                throw new NumberFormatException("digit expected " + (char) c
                        + " found");
            }
            ret = ret * 10 + c - '0';
            c = read();
        }
        return ret * sgn;
    }

    }

class FastPrinter extends PrintWriter {

    public FastPrinter(OutputStream out) {
        super(out);
    }

    public FastPrinter(Writer out) {
        super(out);
    }

}


//package round179;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class D {
	InputStream is;
	PrintWriter out;
	String INPUT = "";
	int mod = 1000000007;
	int[][] fif = enumFIF(7000, mod);

	void solve()
	{
		int n = ni(), m = ni();

		long ret = 0;
		for(int w = 1;w < m;w++){
			long[] num = new long[n+1];
			long[] cum = new long[n+1];
			for(int L = 1;L <= n;L++){
				num[L] = C(w-1+2*(L-1), 2*(L-1));
				cum[L] = cum[L-1] + num[L];
				if(cum[L] >= mod)cum[L]-=mod;
			}

			long lsum = 0;
			for(int L = 1;L <= n;L++){
				lsum += num[L]*cum[n-L+1]%mod*(m-w)%mod;
			}
			ret += lsum%mod;
		}
		out.println(ret%mod);
	}

	long C(int n, int r)
	{
		if(n < 0 || r < 0 || n < r)return 0;
		return (long)fif[0][n]*fif[1][r]%mod*fif[1][n-r]%mod;
	}

	public static int[][] enumFIF(int n, int mod)
	{
		int[] f = new int[n+1];
		int[] invf = new int[n+1];
		invf[1] = 1;
		for(int i = 2;i <= n;i++){
			invf[i] = (int)(invf[mod%i]*(long)(mod-mod/i)%mod);
		}

		f[0] = invf[0] = 1;
		for(int i = 1;i <= n;i++){
			f[i] = (int)((long)f[i-1] * i % mod);
			invf[i] = (int)((long)invf[i-1] * invf[i] % mod);
		}
		return new int[][]{f, invf};
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new D().run(); }

	private byte[] inbuf = new byte[1024];
	private int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


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

public class D_fast {

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

	static final int MOD = 1_000_000_007;

	void solve() throws IOException {
		int n = nextInt();
		int m = nextInt();
		if (m < 2) {
			out.println(0);
			return;
		}

		int[][] dp = new int[n + 1][m + 1];
		for (int len = 2; len <= m; len++) {
			dp[1][len] = 1;
		}

		int[] tmp = new int[m + 1];

		for (int height = 2; height <= n; height++) {
			int[] dpPrev = dp[height - 1];
			tmp[2] = dpPrev[2];
			for (int i = 3; i <= m; i++) {
				tmp[i] = tmp[i - 1] + dpPrev[i];
				if (tmp[i] >= MOD)
					tmp[i] -= MOD;
			}

			int[] dpCur = dp[height];
			dpCur[2] = tmp[2];
			for (int i = 3; i <= m; i++) {
				dpCur[i] = dpCur[i - 1] + tmp[i];
				if (dpCur[i] >= MOD)
					dpCur[i] -= MOD;
			}
		}

		int[] fixedHeight = new int[n + 1];
		int[] up = new int[n + 1];
		int[] down = new int[n + 1];

		int ans = 0;
		for (int len = 2; len <= m; len++) {

			int val = 0;

			for (int h = 1; h <= n; h++) {
				up[h] = down[h] = dp[h][len];
				if (h != 1) {
					up[h] -= dp[h - 1][len];
					if (up[h] < 0)
						up[h] += MOD;
				}
				if (h != 1) {
					up[h] += up[h - 1];
					if (up[h] >= MOD)
						up[h] -= MOD;
					down[h] += down[h - 1];
					if (down[h] >= MOD)
						down[h] -= MOD;
				}
			}

			for (int mid = 0; mid < n; mid++) {
				int maxUp = mid + 1;
				int maxDown = n - mid;
				val += (int)((long)up[maxUp] * down[maxDown] % MOD);
				if (val >= MOD)
					val -= MOD;
			}

			ans += (int) ((long) val * (m - len + 1) % MOD);
			if (ans >= MOD)
				ans -= MOD;
		}

		out.println(ans);

	}

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

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