#include <iostream>
#include <cstdio>
#define shl(x) ((x)<<1)
using namespace std;

const int N = 3e5+5, M = 4e6+5, _n = 1e6;
int
    n,m,a[N],b[N],lz[M],it[M],q;

void Down(int k)
{
    int &tmp = lz[k];

    it[shl(k)] += tmp;
    lz[shl(k)] += tmp;

    it[shl(k)+1] += tmp;
    lz[shl(k)+1] += tmp;

    tmp = 0;
}
void update(int k,int l,int r,int i,int x) /// [ 1 , i ]
{
    if (i < l) return;
    if (r <=i) {
        it[k] += x;
        lz[k] += x;
    } else {
        Down(k);
        int m = (l+r) >> 1;
        update(shl(k), l, m, i, x);
        update(shl(k)+1, m+1, r, i, x);
        it[k] = max(it[shl(k)], it[shl(k)+1]);
    }
}
int get(int k,int l,int r,int i) /// [ i , _n ]
{
    if (r < i) return 0;
    if (i <=l) return it[k];
    Down(k);
    int m = (l+r) >> 1;
    return max(get(shl(k), l, m, i), get(shl(k)+1, m+1, r, i));
}
int bs()
{
    if (get(1,1,_n,1) <= 0) return -1;

    int l = 1, r = _n, m;
    while (l<r) {
        m = (l+r+1) >> 1;
        if (get(1,1,_n,m) > 0) l = m; else r = m-1;
    }
    return r;
}
int main()
{
    //freopen("a.inp","r",stdin);

    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; ++i) scanf("%d",a+i);
    for(int i=1; i<=m; ++i) scanf("%d",b+i);

    for(int i=1; i<=n; ++i) update(1,1,_n,a[i],+1);
    for(int i=1; i<=m; ++i) update(1,1,_n,b[i],-1);

    scanf("%d",&q); while (q--) {
        int t, i, x;
        scanf("%d%d%d",&t,&i,&x);
        if (t == 1) {
            update(1,1,_n,a[i],-1);
            update(1,1,_n,x,1);
            a[i] = x;
        } else {
            update(1,1,_n,b[i],1);
            update(1,1,_n,x,-1);
            b[i] = x;
        }
        printf("%d\n",bs());
    }
}


#include <iostream>
#include <cstdio>
#define ii pair<int,int>
#define shl(x) ((x)<<1)
using namespace std;

const int N = 3e5+5, M = 4e6+5, _n = 1e6;
int
    n,m,a[N],b[N],lz[M],q;
ii it[M];

void build(int k,int l,int r)
{
    if (l == r) {
        it[k] = ii(0, l);
    } else {
        int m = (l+r) >> 1;
        build(shl(k), l, m);
        build(shl(k)+1, m+1, r);
        it[k] = max(it[shl(k)], it[shl(k)+1]);
    }
}
void Down(int k)
{
    int &tmp = lz[k];

    it[shl(k)].first += tmp;
    lz[shl(k)] += tmp;

    it[shl(k)+1].first += tmp;
    lz[shl(k)+1] += tmp;

    tmp = 0;
}
void update(int k,int l,int r,int u,int v,int x)
{
    if (v < l || r < u) return;
    if (u <=l && r <=v) {
        it[k].first += x;
        lz[k] += x;
    } else {
        Down(k);
        int m = (l+r) >> 1;
        update(shl(k), l, m, u, v, x);
        update(shl(k)+1, m+1, r, u, v, x);
        it[k] = max(it[shl(k)], it[shl(k)+1]);
    }
}
int main()
{
    //freopen("a.inp","r",stdin);

    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; ++i) scanf("%d",a+i);
    for(int i=1; i<=m; ++i) scanf("%d",b+i);

    build(1,1,_n);
    for(int i=1; i<=n; ++i) update(1,1,_n,1,a[i],+1);
    for(int i=1; i<=m; ++i) update(1,1,_n,1,b[i],-1);

    scanf("%d",&q); while (q--) {
        int t, i, x;
        scanf("%d%d%d",&t,&i,&x);
        if (t == 1) {
            update(1,1,_n,1,a[i],-1);
            update(1,1,_n,1,x,1);
            a[i] = x;
        } else {
            update(1,1,_n,1,b[i],1);
            update(1,1,_n,1,x,-1);
            b[i] = x;
        }
        if (it[1].first <= 0)
            puts("-1"); else
            printf("%d\n",it[1].second);
    }
}


#include <bits/stdc++.h>
using namespace std;
#define io_speed_up ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=a;i>=b;i--)
#define ms(a,b)  memset(a,b,sizeof a)
#define sz(x) (int)x.size()
using ll = long long;
const int inf = 0x3f3f3f3f;
const int maxn = 1e6+5;
const int N = 1e6;
#define li i<<1
#define ri (i<<1)|1
#define lson li,L,mid
#define rson ri,mid+1,R
struct node{
	int mn, sa, sb;
	node operator+(const node &o) const {
		return {min(mn, o.mn + sb - sa), sa + o.sa, sb + o.sb};
	}
} nd[maxn * 4];
int na[maxn], nb[maxn];
void build(int i,int L=1,int R=N)
{
	if(L==R) {
		int x = N - L + 1;
		nd[i] = {nb[x] - na[x], na[x], nb[x]};
		return;
	}
	int mid = (L + R) >> 1;
	build(lson);
	build(rson);
	nd[i] = nd[li] + nd[ri];
}
void modify(int i,int L,int R,int pos) {
	if(L==R) {
		int x = N - L + 1;
		nd[i] = {nb[x] - na[x], na[x], nb[x]};
		return;
	}
	int mid = (L + R) >> 1;
	if(mid>=pos) modify(lson,pos);
	else modify(rson,pos);
	nd[i] = nd[li] + nd[ri];
}
int ask(int i,int L,int R,int v)
{
	if(L==R) return N-L+1;
	int mid = (L + R) >> 1;
	if(nd[li].mn < v) return ask(lson,v);
	return ask(rson, v - (nd[li].sb - nd[li].sa));
}
int n, m, q;
int a[maxn], b[maxn];
int main()
{
	scanf("%d%d", &n, &m);
	rep(i,1,n) {
		scanf("%d", &a[i]);
		na[a[i]]++;
	}
	rep(i,1,m) {
		scanf("%d", &b[i]);
		nb[b[i]]++;
	}
	build(1);
	scanf("%d", &q);
	while(q--) {
		int op, x, y;
		scanf("%d%d%d", &op, &x, &y);
		if(op==1) {
			na[a[x]]--;
			modify(1, 1, N, N - a[x] + 1);
			na[y]++;
			a[x] = y;
		} else {
			nb[b[x]]--;
			modify(1, 1, N, N - b[x] + 1);
			nb[y]++;
			b[x] = y;
		}
		modify(1, 1, N, N - y + 1);
		if(nd[1].mn>=0) puts("-1");else printf("%d\n",ask(1,1,N,0));
	}
	return 0;
}


#include<stdio.h>
#include<algorithm>
using namespace std;

const int maxn=300000+10;
const int maxm=1000000;

struct node{
  int sum;
  int minz;
};

int m,n,nn=0,q;
int a[maxn];
int b[maxn];
node it[4*(maxm+1)];
int id,ii,xx;

node join(node a,node b){
  node res;
  res.sum=a.sum+b.sum;
  res.minz=min(b.minz,a.minz+b.sum);
  return res;
}

void Update(int k,int l,int r,int i,int val){
  if (r<i || i<l) return;
  if (l==r){
    it[k].sum+=val;
    it[k].minz=it[k].sum;
    return;
  }
  int mid=(l+r)/2;
  Update(k*2,l,mid,i,val);
  Update(k*2+1,mid+1,r,i,val);
  it[k]=join(it[k*2],it[k*2+1]);
}

int Query(int k,int l,int r,int R){
  if (it[k].minz+R>=0) return -1;
  if (l==r) return l;
  int mid=(l+r)/2;
  if (it[k*2+1].minz+R<0) return Query(k*2+1,mid+1,r,R);
  else return Query(k*2,l,mid,it[k*2+1].sum+R);
}

int main(){
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++) scanf("%d",&a[i]);
  for(int i=1;i<=m;i++) scanf("%d",&b[i]);
  //----------
  for(int i=1;i<=n;i++) Update(1,1,maxm,a[i],-1);
  for(int i=1;i<=m;i++) Update(1,1,maxm,b[i],+1);
  //----------
  scanf("%d",&q);
  for(int qq=1;qq<=q;qq++){
    scanf("%d%d%d",&id,&ii,&xx);
    if (id==1){
      Update(1,1,maxm,a[ii],+1);
      Update(1,1,maxm,xx,-1);
      a[ii]=xx;
    }
    if (id==2){
      Update(1,1,maxm,b[ii],-1);
      Update(1,1,maxm,xx,+1);
      b[ii]=xx;
    }
    int kq=Query(1,1,maxm,0);
    printf("%d\n",kq);
  }
}


#include<bits/stdc++.h>
using namespace std;
const int N=3e5+50,M=1e6+1;
int n,m,q,a[N],b[N];
struct node{
	int l,r,mx,laz;
}t[M*4];
void build(int x,int l,int r){
	t[x].l=l;t[x].r=r;
	if(l==r)return;
	int mid=(l+r)>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
}
void change(int x,int l,int r,int k){
	if(t[x].r<=r){
		t[x].mx+=k,t[x].laz+=k;
		return;
	}
	if(t[x].laz){
		change(x<<1,1,M-1,t[x].laz);
		change(x<<1|1,1,M-1,t[x].laz);
		t[x].laz=0;
	}
	int mid=(t[x].l+t[x].r)>>1;
	change(x<<1,l,r,k);
	if(r>mid)change(x<<1|1,l,r,k);
	t[x].mx=max(t[x<<1].mx,t[x<<1|1].mx);
}
int ask(){
	int x=1;
	while(t[x].l!=t[x].r){
		if(t[x].laz){
			change(x<<1,1,M,t[x].laz);
			change(x<<1|1,1,M,t[x].laz);
			t[x].laz=0;
		}
		if(t[x<<1|1].mx>0)x=x<<1|1;
		else x<<=1;
	}
	if(t[x].mx>0)return t[x].l;
	return -1;
}
int main(){
	scanf("%d%d",&n,&m);
	build(1,1,M-1);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),change(1,1,a[i],1);
	for(int i=1;i<=m;i++)scanf("%d",&b[i]),change(1,1,b[i],-1);
	scanf("%d",&q);
	for(int i=1,k,x,y;i<=q;i++){
		scanf("%d%d%d",&k,&x,&y);
		if(k==1)change(1,1,a[x],-1),a[x]=y,change(1,1,a[x],1);
		else change(1,1,b[x],1),b[x]=y,change(1,1,b[x],-1);
		printf("%d\n",ask());
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=300010;
const int INF=0x7fffffff;
int tot,root,n,m,q,opt,val,x,a[MAXN],s[MAXN];
struct Treap{
    int l,r;
    int val,date;
    int cnt,size;
}tree[MAXN];
int New(int val){
    tot++;
    tree[tot].val=val;
    tree[tot].date=rand();
    tree[tot].cnt=1;
    tree[tot].size=1;
    return tot;
}
void Update(int p){
    tree[p].size=tree[tree[p].l].size+tree[tree[p].r].size+tree[p].cnt;
}
void build(){
	tot=0;
	memset(tree,0,sizeof(tree));
    New(-INF);
    New(INF);
    root=1;
    tree[1].r=2;
    Update(root);
}
void zig(int &p){
    int q=tree[p].l;
    tree[p].l=tree[q].r;
    tree[q].r=p;
    p=q;
    Update(tree[p].r);
    Update(p);
}
void zag(int &p){
    int q=tree[p].r;
    tree[p].r=tree[q].l;
    tree[q].l=p;
    p=q;
    Update(tree[p].l);
    Update(p);
}
void Insert(int &p,int val){
    if (!p){
        p=New(val);
        return;
    }
    if (tree[p].val==val){
        tree[p].cnt++;
        Update(p);
        return;
    }
    if (tree[p].val>val){
        Insert(tree[p].l,val);
        if (tree[p].date<tree[tree[p].l].date) zig(p);
    }else{
        Insert(tree[p].r,val);
        if (tree[p].date<tree[tree[p].r].date) zag(p);
    }
    Update(p);
}
void Remove(int &p,int val){
    if (!p) return;
    if (tree[p].val==val){
        if (tree[p].cnt>1){
            tree[p].cnt--;
            Update(p);
            return;
        }
        if (tree[p].l||tree[p].r){
            if (!tree[p].r||tree[tree[p].l].date>tree[tree[p].r].date){
                zig(p);
                Remove(tree[p].r,val);
            }else{
                zag(p);
                Remove(tree[p].l,val);
            }
            Update(p);
        }else p=0;
        return;
    }
    if (tree[p].val>val) Remove(tree[p].l,val);
        else Remove(tree[p].r,val);
    Update(p);
}
int Get_Rank(int p,int val){
    if (!p) return 0;
    if (tree[p].val==val)
        return tree[tree[p].l].size+1;
    if (val<tree[p].val)
        return Get_Rank(tree[p].l,val);
    return Get_Rank(tree[p].r,val)+tree[tree[p].l].size+tree[p].cnt;
}
int Get_Val(int p,int rank){
    if (!p) return INF;
    if (tree[tree[p].l].size>=rank)
        return Get_Val(tree[p].l,rank);
    if (tree[tree[p].l].size+tree[p].cnt>=rank)
        return tree[p].val;
    return Get_Val(tree[p].r,rank-tree[tree[p].l].size-tree[p].cnt);
}
int Get_pre(int val){
    int ans=1;
    int p=root;
    while (p){
        if (tree[p].val==val){
            if (tree[p].l){
                p=tree[p].l;
                while(tree[p].r>0)
                    p=tree[p].r;
                ans=p;
            }
            break;
        }
        if (tree[p].val<val&&tree[p].val>tree[ans].val)
            ans=p;
        if (tree[p].val>val) p=tree[p].l;
            else p=tree[p].r;
    }
    return tree[ans].val;
}
int Get_nxt(int val){
    int ans=2;
    int p=root;
    while (p){
        if (tree[p].val==val){
            if (tree[p].r){
                p=tree[p].r;
                while(tree[p].l)
                    p=tree[p].l;
                ans=p;
            }
            break;
        }
        if (tree[p].val>val&&tree[p].val<tree[ans].val)
            ans=p;
        if (tree[p].val>val) p=tree[p].l;
            else p=tree[p].r;
    }
    return ans;
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++){
        scanf("%d",&s[i]);
	}
    for (int i=1; i<=m; i++){
        scanf("%d",&a[i]);
	}
	scanf("%d",&q);
	for (int k=1; k<=q; k++){
		scanf("%d%d%d",&opt,&x,&val);
		if (opt==1) s[x]=val;
		if (opt==2) a[x]=val;
    	build();
    	for (int i=1; i<=n; i++){
        	Insert(root,s[i]);
		}
		for (int i=1; i<=m; i++){
			if (Get_pre(a[i]+1)!=-INF) Remove(root,Get_pre(a[i]+1));
		}
		if (Get_pre(INF)==-INF){
			printf("-1\n");
			continue;
		}
		int ans=Get_pre(INF);
		printf("%d\n",ans);
	}
}


#include <bits/stdc++.h>

using namespace std;

#define int long long

const int MAXN = 3e5 + 7;
const int MAXV = 3 * MAXN;

int n, m;
int a[MAXN], b[MAXN];

int q;
int t[MAXN], p[MAXN], x[MAXN];

void read() {
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    for (int i = 0; i < m; ++i) {
        cin >> b[i];
    }
    cin >> q;
    for (int i = 0; i < q; ++i) {
        cin >> t[i];
        if (t[i] <= 2) {
            cin >> p[i] >> x[i];
            --p[i];
        }
    }
}

int u = 0;
int v[MAXV];

void compr() {
    for (int i = 0; i < n; ++i) {
        v[u++] = a[i];
    }
    for (int i = 0; i < m; ++i) {
        v[u++] = b[i];
    }
    for (int i = 0; i < q; ++i) {
        if (t[i] <= 2) {
            v[u++] = x[i];
        }
    }
    sort(v, v + u);
    u = unique(v, v + u) - v;
    for (int i = 0; i < n; ++i) {
        a[i] = lower_bound(v, v + u, a[i]) - v;
    }
    for (int i = 0; i < m; ++i) {
        b[i] = lower_bound(v, v + u, b[i]) - v;
    }
    for (int i = 0; i < q; ++i) {
        if (t[i] <= 2) {
            x[i] = lower_bound(v, v + u, x[i]) - v;
        }
    }
}

int tree[MAXV << 2], add[MAXV << 2];

void push(int v) {
    tree[v * 2 + 1] += add[v];
    add[v * 2 + 1] += add[v];
    tree[v * 2 + 2] += add[v];
    add[v * 2 + 2] += add[v];
    add[v] = 0;
}

void upd(int v, int tl, int tr, int l, int r, int x) {
    if (tr < l || r < tl) {
        return;
    }
    if (l <= tl && tr <= r) {
        tree[v] += x;
        add[v] += x;
        return;
    }
    int tm = (tl + tr) >> 1;
    push(v);
    upd(v * 2 + 1, tl, tm, l, r, x);
    upd(v * 2 + 2, tm + 1, tr, l, r, x);
    tree[v] = max(tree[v * 2 + 1], tree[v * 2 + 2]);
}

int get(int v, int tl, int tr) {
    if (tl == tr) {
        return tl;
    }
    int tm = (tl + tr) >> 1;
    push(v);
    if (tree[v * 2 + 2] >= 1) {
        return get(v * 2 + 2, tm + 1, tr);
    }
    else {
        return get(v * 2 + 1, tl, tm);
    }
}

void add1(int x) {
    //cout << x << ' ' << 1 << '\n';
    upd(0, 0, MAXV, 0, x, 1);
}

void del1(int x) {
    //cout << x << ' ' << -1 << '\n';
    upd(0, 0, MAXV, 0, x, -1);
}

void upd1(int p, int x) {
    del1(a[p]);
    a[p] = x;
    add1(a[p]);
}

void add2(int x) {
    //cout << x << ' ' << -1 << '\n';
    upd(0, 0, MAXV, 0, x, -1);
}

void del2(int x) {
    //cout << x << ' ' << 1 << '\n';
    upd(0, 0, MAXV, 0, x, 1);
}

void upd2(int p, int x) {
    del2(b[p]);
    b[p] = x;
    add2(b[p]);
}

int get() {
    if (tree[0] >= 1) {
        return get(0, 0, MAXV);
    }
    else {
        return -1;
    }
}

void solve() {
    compr();
    for (int i = 0; i < n; ++i) {
        add1(a[i]);
    }
    for (int i = 0; i < m; ++i) {
        add2(b[i]);
    }
}

void print() {
    for (int i = 0; i < q; ++i) {
        if (t[i] == 1) {
            upd1(p[i], x[i]);
        }
        else {
            upd2(p[i], x[i]);
        }
        {
            int ans = get();
            if (ans == -1) {
                cout << "-1\n";
            }
            else {
                cout << v[ans] << '\n';
            }
        }
    }
}

signed main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    read();
    solve();
    print();

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=100010;
const int INF=0x7fffffff;
int tot,root,n,m,q,opt,val,x,a[MAXN],s[MAXN];
struct Treap{
    int l,r;
    int val,date;
    int cnt,size;
}tree[MAXN];
int New(int val){
    tot++;
    tree[tot].val=val;
    tree[tot].date=rand();
    tree[tot].cnt=1;
    tree[tot].size=1;
    return tot;
}
void Update(int p){
    tree[p].size=tree[tree[p].l].size+tree[tree[p].r].size+tree[p].cnt;
}
void build(){
	tot=0;
	memset(tree,0,sizeof(tree));
    New(-INF);
    New(INF);
    root=1;
    tree[1].r=2;
    Update(root);
}
void zig(int &p){
    int q=tree[p].l;
    tree[p].l=tree[q].r;
    tree[q].r=p;
    p=q;
    Update(tree[p].r);
    Update(p);
}
void zag(int &p){
    int q=tree[p].r;
    tree[p].r=tree[q].l;
    tree[q].l=p;
    p=q;
    Update(tree[p].l);
    Update(p);
}
void Insert(int &p,int val){
    if (!p){
        p=New(val);
        return;
    }
    if (tree[p].val==val){
        tree[p].cnt++;
        Update(p);
        return;
    }
    if (tree[p].val>val){
        Insert(tree[p].l,val);
        if (tree[p].date<tree[tree[p].l].date) zig(p);
    }else{
        Insert(tree[p].r,val);
        if (tree[p].date<tree[tree[p].r].date) zag(p);
    }
    Update(p);
}
void Remove(int &p,int val){
    if (!p) return;
    if (tree[p].val==val){
        if (tree[p].cnt>1){
            tree[p].cnt--;
            Update(p);
            return;
        }
        if (tree[p].l||tree[p].r){
            if (!tree[p].r||tree[tree[p].l].date>tree[tree[p].r].date){
                zig(p);
                Remove(tree[p].r,val);
            }else{
                zag(p);
                Remove(tree[p].l,val);
            }
            Update(p);
        }else p=0;
        return;
    }
    if (tree[p].val>val) Remove(tree[p].l,val);
        else Remove(tree[p].r,val);
    Update(p);
}
int Get_Rank(int p,int val){
    if (!p) return 0;
    if (tree[p].val==val)
        return tree[tree[p].l].size+1;
    if (val<tree[p].val)
        return Get_Rank(tree[p].l,val);
    return Get_Rank(tree[p].r,val)+tree[tree[p].l].size+tree[p].cnt;
}
int Get_Val(int p,int rank){
    if (!p) return INF;
    if (tree[tree[p].l].size>=rank)
        return Get_Val(tree[p].l,rank);
    if (tree[tree[p].l].size+tree[p].cnt>=rank)
        return tree[p].val;
    return Get_Val(tree[p].r,rank-tree[tree[p].l].size-tree[p].cnt);
}
int Get_pre(int val){
    int ans=1;
    int p=root;
    while (p){
        if (tree[p].val==val){
            if (tree[p].l){
                p=tree[p].l;
                while(tree[p].r>0)
                    p=tree[p].r;
                ans=p;
            }
            break;
        }
        if (tree[p].val<val&&tree[p].val>tree[ans].val)
            ans=p;
        if (tree[p].val>val) p=tree[p].l;
            else p=tree[p].r;
    }
    return tree[ans].val;
}
int Get_nxt(int val){
    int ans=2;
    int p=root;
    while (p){
        if (tree[p].val==val){
            if (tree[p].r){
                p=tree[p].r;
                while(tree[p].l)
                    p=tree[p].l;
                ans=p;
            }
            break;
        }
        if (tree[p].val>val&&tree[p].val<tree[ans].val)
            ans=p;
        if (tree[p].val>val) p=tree[p].l;
            else p=tree[p].r;
    }
    return ans;
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++){
        scanf("%d",&s[i]);
	}
    for (int i=1; i<=m; i++){
        scanf("%d",&a[i]);
	}
	scanf("%d",&q);
	for (int k=1; k<=q; k++){
		scanf("%d%d%d",&opt,&x,&val);
		if (opt==1) s[x]=val;
		if (opt==2) a[x]=val;
    	build();
    	for (int i=1; i<=n; i++){
        	Insert(root,s[i]);
		}
		for (int i=1; i<=m; i++){
			if (Get_pre(a[i]+1)!=-INF) Remove(root,Get_pre(a[i]+1));
		}
		if (Get_pre(INF)==-INF){
			printf("-1\n");
			continue;
		}
		int ans=Get_pre(INF);
		printf("%d\n",ans);
	}
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll N, M, Q, P, A[300005], B[300005], C, D, E, F, G, H, X, Y, Z;

string s;

struct node{
	node *left = nullptr, *right = nullptr;
	int s, e, val = 0, lazyadd = 0;
	node (int _s, int _e){
		s = _s;
		e = _e;
		if (s != e){
			left = new node(s,(s+e)/2);
			right = new node((s+e)/2+1,e);
		}
	}
	void propagate(){
		if (lazyadd){
			left->val += lazyadd;
			right->val += lazyadd;
			left->lazyadd += lazyadd;
			right->lazyadd += lazyadd;
			lazyadd = 0;
		}
	}
	void update(int l, int r, int v){
		if (l > e || r < s) return;
		if (l <= s && e <= r){
			val += v;
			lazyadd += v;
			return;
		}
		propagate();
		left->update(l,r,v);
		right->update(l,r,v);
		val = min(left->val,right->val);
	}
	int traverse(){
		if (val >= 0){
			return -1;
		}
		if (s == e) return s;
		propagate();
		if (right->val < 0){
			return right->traverse();
		}
		else return left->traverse();
	}
} *root;

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cin >> N >> M;
	root = new node(1,1000000);
	for (int i = 1; i <= N; ++i){
		cin >> A[i];
		root->update(1,A[i],-1);
	}
	for (int j = 1; j <= M; ++j){
		cin >> B[j];
		root->update(1,B[j],1);
	}
	cin >> Q;
	for (int i = 1; i <= Q; ++i){
		cin >> X >> Y >> Z;
		if (X == 1){
			root->update(1,A[Y],1);
			A[Y] = Z;
			root->update(1,A[Y],-1);
		}
		else{
			root->update(1,B[Y],-1);
			B[Y] = Z;
			root->update(1,B[Y],1);
		}
		cout << root->traverse() << '\n';
	}
}


#include <bits/stdc++.h>
#define N 1000011
#define K 1000000

using namespace std;

int n, m;
int A[N], B[N];

/* ----- Segment Tree ----- */
int I, J, val;
int dt[N << 2];
int st[N << 2];

void push(int p, int l, int r) {
	if(dt[p] == 0) return;
	st[p] += dt[p];
	if(r > l) {
		dt[2*p] += dt[p];
		dt[2*p+1] += dt[p];
	}
	dt[p] = 0;
}

void update(int p, int l, int r) {
	push(p,l,r);
	if(l > J or r < I) return;
	if(l >= I and r <= J) {
		dt[p] += val;
		push(p,l,r);
	}
	else {
		int M = (l + r) >> 1;
		int P = p << 1;
		update(P, l, M);
		update(P|1, M+1, r);
		st[p] = max(st[P], st[P|1]);
	}
}

int query(int p, int l, int r) {
	push(p,l,r);
	if(l == r) {
		if(st[p] > 0) return l;
		return -1;
	}
	else {
		int M = (l + r) >> 1;
		int P = p << 1;
        push(P,l,M); push(P|1,M+1,r);
		if(st[P|1] > 0) return query(P|1, M+1, r);
		return query(P, l, M);
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >> n >> m;
	for(int i=0; i<n; i++) {
		cin >> A[i];
		I = 0; J = A[i]; val = 1;
		update(1, 1, K);
	}
	for(int i=0; i<m; i++) {
		cin >> B[i];
		I = 0; J = B[i]; val = -1;
		update(1, 1, K);
	}
	int q;
	cin >> q;
	while(q--) {
		int typ, x, y;
		cin >> typ >> x >> y;
		x--;
		if(typ == 1) {
			I = 0; J = A[x]; val = -1;
			update(1, 1, K);
			J = A[x] = y; val = 1;
			update(1, 1, K);
		}
		else {
			I = 0; J = B[x]; val = 1;
			update(1, 1, K);
			J = B[x] = y; val = -1;
			update(1, 1, K);
		}
		int ans = query(1, 1, K);
		cout << ans << endl;
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int INF=2018061000;
int n,m,q,a[300005],b[300005],cnt[1000005];
struct node{
	int l,r,val,add;
} s[4000005];
void build(int k,int l,int r){
	s[k].l=l;s[k].r=r;s[k].val=INF;s[k].add=0;
	if(l==r)	return;
    int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
}
void pushdown(int k){
	if(s[k].add){
		s[k<<1].add+=s[k].add;
		s[k<<1|1].add+=s[k].add;
		s[k<<1].val+=s[k].add;
		s[k<<1|1].val+=s[k].add;
		s[k].add=0;
    }
}
void change(int k,int l,int r,int v){
    if(l<=s[k].l&&s[k].r<=r){
        s[k].val+=v;
		s[k].add+=v;
        return;
    }
    pushdown(k);
    int mid=(s[k].l+s[k].r)>>1;
    if(r<=mid)		change(k<<1,l,r,v);
    else if(l>mid)	change(k<<1|1,l,r,v);
    else			change(k<<1,l,mid,v),change(k<<1|1,mid+1,r,v);
    s[k].val=min(s[k<<1].val,s[k<<1|1].val);
}
int ask(int k){
    if(s[k].val>=0)		return -1;
    if(s[k].l==s[k].r)	return s[k].l;
    pushdown(k);
    int mid=(s[k].l+s[k].r)>>1;
    if(s[k<<1|1].val<0)		return ask(k<<1|1);
    else					return ask(k<<1);
}
int main(){
    scanf("%d%d",&n,&m);
    build(1,1,1000000);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        cnt[a[i]]++;
		if(cnt[a[i]]==1)	change(1,a[i],a[i],-INF);
        change(1,1,a[i],-1);
    }
    for(int i=1;i<=m;i++){
        scanf("%d",&b[i]);
        change(1,1,b[i],1);
    }
    scanf("%d",&q);
    while(q--){
        int opt,i,x;
        scanf("%d%d%d",&opt,&i,&x);
        if(opt==1){
            change(1,1,a[i],1);
            cnt[a[i]]--;
			if(cnt[a[i]]==0)	change(1,a[i],a[i],INF);
            a[i]=x;
			change(1,1,a[i],-1);
			cnt[a[i]]++;
			if(cnt[a[i]]==1)	change(1,a[i],a[i],-INF);
        }
        else{
            change(1,1,b[i],-1);
            b[i]=x;
            change(1,1,b[i],1);
        }
        printf("%d\n",ask(1));
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int N = 300005, M = 1000005;
int n, m, q, a[N], b[N];

struct SegmentTree {
	int val[M << 2], lzy[M << 2];

	#define mid (l + r >> 1)
	#define ls (p << 1)
	#define rs (p << 1 | 1)

	inline void pushup(int p) {
		val[p] = max(val[ls], val[rs]);
	}

	inline void tag(int p, int v) {
		val[p] += v, lzy[p] += v;
	}
	inline void pushdown(int p) {
		if(lzy[p]) {
			tag(ls, lzy[p]), tag(rs, lzy[p]);
			lzy[p] = 0;
		}
	}
	void add(int p, int l, int r, int ql, int qr, int v) {
		if(ql <= l && r <= qr) return tag(p, v);
		pushdown(p);
		if(mid >= ql) add(ls, l, mid, ql, qr, v);
		if(mid < qr) add(rs, mid + 1, r, ql, qr, v);
		pushup(p);
	}
	int query(int p = 1, int l = 1, int r = 1e6) {
		if(l == r) return l;
		pushdown(p);
		if(val[rs] > 0) return query(rs, mid + 1, r);
		else return query(ls, l, mid);
	}
} smt;

int main() {
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), smt.add(1, 1, 1e6, 1, a[i], 1);
	for(int i = 1; i <= m; ++i) scanf("%d", &b[i]), smt.add(1, 1, 1e6, 1, b[i], -1);
	scanf("%d", &q);
	for(int i = 1, op, p, x; i <= q; ++i) {
		scanf("%d%d%d", &op, &p, &x);
		if(op & 1) {
			smt.add(1, 1, 1e6, 1, a[p], -1);
			smt.add(1, 1, 1e6, 1, a[p] = x, 1);
		} else {
			smt.add(1, 1, 1e6, 1, b[p], 1);
			smt.add(1, 1, 1e6, 1, b[p] = x, -1);
		}
		if(smt.val[1] <= 0) puts("-1");
		else printf("%d\n", smt.query());
	}
	return 0;
}


#include <bits/stdc++.h>
#define debug(x) (cout << "#x = " << (x) << '\n')

using namespace std;
typedef long long ll;

inline char gc() {
	static char buf[100000], *p1 = buf, *p2 = buf;
	return (p1 == p2) && (p2 = (p1 = buf) +
		fread(buf, 1, 100000, stdin), p1 == p2)? EOF: *p1++;
}

#define dd ch = getchar()
template <class T>
inline void read(T &x) {
	x = 0;
	int f = 0; char dd;
	for (; !isdigit(ch); dd) f ^= (ch == '-');
	for (; isdigit(ch); dd)  x = (x << 1) + (x << 3) + (ch ^ 48);
	x = f? -x: x;
}
#undef dd

template <class T>
inline void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 | 48);
}

template <class T>
inline void wrn(T x) {
	write(x), putchar(' ');
}

template <class T>
inline void wln(T x) {
	write(x), putchar('\n');
}

template <class T>
inline void wlnn(T x, T y) {
	wrn(x), wln(y);
}

const int N = 3e5 + 5;
const int M = 1e6 + 5;

int n, m, a[N], b[N];

#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
#define mid ((l + r) >> 1)

int T[M << 2], mx[M << 2];

inline void pushUp(int p) {
	T[p] = T[ls(p)] + T[rs(p)];
	mx[p] = max(mx[rs(p)], mx[ls(p)] + T[rs(p)]);
}

inline void Update(int p, int l, int r, int x, int k) {
	if (l == r)
		return (void) (T[p] += k, mx[p] += k);
	if (x <= mid) Update(ls(p), l, mid, x, k);
	if (x > mid)  Update(rs(p), mid + 1, r, x, k);
	pushUp(p);
}

inline int Query(int p, int l, int r, int sum) {
	if (l == r) return l;
	int S = sum + T[rs(p)], X = sum + mx[rs(p)];
	if (X <= 0) return Query(ls(p), l, mid, S);
	if (X > 0)  return Query(rs(p), mid + 1, r, sum);
}

int main()
{
	read(n), read(m);
	for (int i = 1; i <= n; ++i) read(a[i]);
	for (int i = 1; i <= m; ++i) read(b[i]);
	for (int i = 1; i <= n; ++i) Update(1, 1, 1e6, a[i], 1);
	for (int i = 1; i <= m; ++i) Update(1, 1, 1e6, b[i], -1);

	int Q, opt, i, x;
	for (read(Q); Q; --Q) {
		read(opt), read(i), read(x);
		if (opt == 1) {
			Update(1, 1, 1e6, a[i], -1);
			Update(1, 1, 1e6, a[i] = x, 1);
		}
		if (opt == 2) {
			Update(1, 1, 1e6, b[i], 1);
			Update(1, 1, 1e6, b[i] = x, -1);
		}
		if (mx[1] <= 0) puts("-1");
		else wln(Query(1, 1, 1e6, 0));
	} return 0;
}

/*

*/


#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int N=1e6+5;
struct node
{
    int l,r,maxx,lazy;
};
node e[N*4];
int a[N],b[N];

void build(int root,int l,int r)
{
    e[root].l=l;
    e[root].r=r;
    e[root].maxx=e[root].lazy=0;
    if(l==r)
        return ;
    build(root*2,l,(l+r)/2);
    build(root*2+1,(l+r)/2+1,r);
}

void updown(int root)
{
    if(e[root].lazy!=0)
    {
        e[root*2].lazy+=e[root].lazy;
        e[root*2+1].lazy+=e[root].lazy;
        e[root*2].maxx+=e[root].lazy;
        e[root*2+1].maxx+=e[root].lazy;
        e[root].lazy=0;
    }
}
void update(int root,int l,int r,int v)
{
    //printf("%d %d\n",e[root].l,e[root].r);
    if(e[root].l>=l&&e[root].r<=r)
    {
        e[root].maxx+=v;
        e[root].lazy+=v;
        return ;
    }
    updown(root);
    int mid=(e[root].l+e[root].r)/2;
    if(l<=mid)
    {
        update(root*2,l,r,v);

    }
    if(r>mid)
    update(root*2+1,l,r,v);
    e[root].maxx=max(e[root*2].maxx,e[root*2+1].maxx);
}
int que(int root,int l,int r)
{
    if(l==r)
        return l;
    updown(root);
    if(e[root*2+1].maxx>0)
        return que(root*2+1,(l+r)/2+1,r);
    else
       return que(root*2,l,(l+r)/2);
}
int main()
{
    int n,m,q,x,y,z;
    scanf("%d %d",&n,&m);
    build(1,1,1e6);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        update(1,1,a[i],1);
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&b[i]);
        update(1,1,b[i],-1);
    }
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d",&z);
        if(z==1)
        {
            scanf("%d %d",&x,&y);
            update(1,1,a[x],-1);
            a[x]=y;
            update(1,1,a[x],1);
        }
        else
        {
            scanf("%d %d",&x,&y);
            update(1,1,b[x],1);
            b[x]=y;
            update(1,1,b[x],-1);
        }
        if(e[1].maxx<=0)
            printf("-1\n");
        else
        printf("%d\n",que(1,1,1e6));
    }
}


#include <bits/stdc++.h>

using namespace std;

const size_t MAXN = 300001;

int data[4001000];
int lazy[4001000];

int a[MAXN], b[MAXN];

void Update(int root, int L, int R, int l, int r, int val) {
    if(lazy[root] != 0) {
        data[root] += lazy[root];
        if(L != R) {
            lazy[root<<1] += lazy[root];
            lazy[root<<1|1] += lazy[root];
        }
        lazy[root] = 0;
    }
    if(L > R || r < L || R < l) { return; }
    if(l <= L && R <= r) {
        data[root] += val;
        if(L != R) {
            lazy[root<<1] += val;
            lazy[root<<1|1] += val;
        }
        return ;
    }
    int mid = (L+R)/2;
    //just for pushdown
    Update(root<<1, L, mid, l, r, val);
    Update(root<<1|1, mid+1, R, l, r, val);
    data[root] = max(data[root<<1], data[root<<1|1]);
}

int Query(int root, int L, int R) {
    if(lazy[root] != 0) {
        data[root] += lazy[root];
        if(L != R) {
            lazy[root<<1] += lazy[root];
            lazy[root<<1|1] += lazy[root];
        }
        lazy[root] = 0;
    }
    //cout << root << "\t" << L << "\t" << R << "\n" << endl;
    if(data[root] <= 0)  {
        return -1;
    }
    if(L == R) {
        return L;
    }
    int mid = (L+R)/2;
    int val = Query(root<<1|1, mid+1, R);
    if(val > 0) {
        return val;
    }
    return Query(root<<1, L, mid);
}

int main() {
    int n, m;
    memset(data, 0, sizeof(data));
    memset(lazy, 0, sizeof(lazy));
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    for(int i = 1; i <= m; ++i) {
        scanf("%d", &b[i]);
    }
    for(int i = 1; i <= n; ++i) {
        Update(1, 1, 1000000, 1, a[i], 1);
    }
    for(int i = 1; i <= m; ++i) {
        Update(1, 1, 1000000, 1, b[i], -1);
    }
    int q = 0;
    scanf("%d", &q);
    for(int i = 1; i <= q; ++i) {
        int t, x, v;
        scanf("%d %d %d", &t, &x, &v);
        if(t == 1) {
            Update(1, 1, 1000000, 1, a[x], -1);
            Update(1, 1, 1000000, 1, v, 1);
            a[x] = v;
        } else {
            Update(1, 1, 1000000, 1, b[x], 1);
            Update(1, 1, 1000000, 1, v, -1);
            b[x] = v;
        }
        //for(int j = 1; j <= 10; ++j) {
        //    cout << "j = " << j << "\t" << Query(1,1,1000000) << endl;
        //}
        printf("%d\n", Query(1, 1, 1000000));
    }
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdbool>
#include <cinttypes>

#define REPEAT(token, num) for (token = 0; token < num; token++)
static inline int64_t min(int64_t length1, int64_t length2) { return (length1 < length2) ? length1 : length2; }
static inline int64_t max(int64_t length1, int64_t length2) { return (length1 > length2) ? length1 : length2; }

//#define DEBUG
#ifdef DEBUG
#define PRINTF printf
#else
#define PRINTF(...)
#endif

typedef struct {
    int64_t cost;
    int64_t index;
} item_key;
typedef int64_t item_value;
typedef int64_t num_items;

int64_t compareKeys(item_key key1, item_key key2) {
    if (key1.cost != key2.cost) return key1.cost-key2.cost;
    return key1.index-key2.index;
}

struct treap {
    item_key key;
    item_value value;
    num_items priority;
    num_items size;
    num_items need;
    num_items excess;
    struct treap *left;
    struct treap *right;
};
struct treap_pair {
    struct treap *left;
    struct treap *right;
};

struct treap space[600010];
num_items numSpaceUsed;

num_items getTreapSize(struct treap *treap1) {
    if (treap1 == NULL) return 0;
    return treap1->size;
}

num_items getTreapNeed(struct treap *treap1) {
    if (treap1 == NULL) return 0;
    return treap1->need;
}

num_items getTreapExcess(struct treap *treap1) {
    if (treap1 == NULL) return 0;
    return treap1->excess;
}

void calcTreapProperties(struct treap *treap1) {
    if (treap1 != NULL) {
        treap1->size = 1+getTreapSize(treap1->left)+getTreapSize(treap1->right);

        num_items needLeft = getTreapNeed(treap1->left);
        num_items excessRight = getTreapExcess(treap1->right);
        if (treap1->value > 0) excessRight++;
        else needLeft++;

        num_items nodesMatched = needLeft;
        if (excessRight < nodesMatched) nodesMatched = excessRight;

        treap1->need = needLeft+getTreapNeed(treap1->right)-nodesMatched;
        treap1->excess = getTreapExcess(treap1->left)+excessRight-nodesMatched;
    }
}

struct treap *newTreap(item_key key, item_value value) {
    if (numSpaceUsed > 600010) fprintf(stderr, "Ran out of treap space"), exit(1);
    space[numSpaceUsed].priority = rand();
    space[numSpaceUsed].key = key;
    space[numSpaceUsed].value = value;
    space[numSpaceUsed].left = NULL;
    space[numSpaceUsed].right = NULL;
    calcTreapProperties(space+numSpaceUsed);
    numSpaceUsed++;
    return space+(numSpaceUsed-1);
}

struct treap *mergeTreaps(struct treap *left, struct treap *right) {
    if (left == NULL) return right;
    if (right == NULL) return left;
    if (left->priority > right->priority) {
        left->right = mergeTreaps(left->right, right);
        calcTreapProperties(left);
        return left;
    } else {
        right->left = mergeTreaps(left, right->left);
        calcTreapProperties(right);
        return right;
    }
}

//Split treap into a left-side with all elements less than or equal to key and a right-side with the rest of the elements.
//Note that if exclusive is true, then left-side will have all elements less than key and right-side will have all elements greater than or equal to key.
struct treap_pair splitByKey(struct treap *treap1, item_key key, bool exclusive) {
    struct treap_pair answer;
    if (treap1 == NULL) {
        answer.left = answer.right = NULL;
        return answer;
    }

    int compareKeysResult = compareKeys(key, treap1->key);
    //If the key is less than the key of the root, then all items less than or equal to key are on the left-hand side.
    if (exclusive ? (compareKeysResult <= 0) : (compareKeysResult < 0)) {
        answer = splitByKey(treap1->left, key, exclusive);
        //Since answer.left is the tree rooted at key, make answer.right, which has all elements greater than key but less than the key of the root, the new left node of the treap:
        treap1->left = answer.right;
        //After making this modification, treap1 becomes the right-side, which has all elements greater than key:
        answer.right = treap1;
    }
    //If the key is greater than or equal to the key of the root, then we know that the left-side and the root is composed of all elements less than or equal to key, so we need to search the right-hand side for any other elements which are less than or equal to key.
    else {
        answer = splitByKey(treap1->right, key, exclusive);
        //Now, we need to combine treap1 and its left-side with all of the elements in the right-side which are also less than or equal to key.
        //These elements are now in answer.left, so make answer.left the new right-side of treap:
        treap1->right = answer.left;
        //After making this modification, treap1 becomes the left-side, which has all elements less than or equal to key:
        answer.left = treap1;
    }
    calcTreapProperties(treap1);
    return answer;
}

bool addElementByKey(struct treap **treapPtr, item_key newKey, item_value newValue, bool exclusive) {
    //Split treap up into a left-side with all elements less than newKey:
    struct treap_pair parts = splitByKey(*treapPtr, newKey, false);
    //Make sure newKey is not already in the tree:
    if (exclusive) {
        struct treap_pair parts2 = splitByKey(parts.left, newKey, true);
        if (parts2.right != NULL) {
            *treapPtr = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right);
            return false;
        }
        parts.left = mergeTreaps(parts2.left, parts2.right);
    }

    //Create a new node:
    struct treap *storeTreap = newTreap(newKey, newValue);
    //Put the new node to the right of the left-side, and then merge the new left-side with the right-side:
    *treapPtr = mergeTreaps(mergeTreaps(parts.left, storeTreap), parts.right);

    return true;
}

bool removeElementByKey(struct treap **treapPtr, item_key oldKey) {
    //Split treap up into a left-side which has all elements up to oldKey:
    struct treap_pair parts = splitByKey(*treapPtr, oldKey, false);
    //Now, split the left-side up into a left-side which has all elements before oldKey and a right-side which has all elements equal to oldKey:
    struct treap_pair parts2 = splitByKey(parts.left, oldKey, true);
    //Record whether there were actually any elements with oldKey:
    bool actuallyRemoved = parts2.right != NULL;
    //Merge treaps back together without the elements equal to oldKey:
    *treapPtr = mergeTreaps(parts2.left, parts.right);

    return actuallyRemoved;
}

item_key getHighestNeed(struct treap *treapPtr) {
    num_items index = getTreapNeed(treapPtr)-1;

    while (true) {
        num_items needLeft = getTreapNeed(treapPtr->left);
        num_items excessRight = getTreapExcess(treapPtr->right);
        if (treapPtr->value > 0) excessRight++;
        else if (excessRight <= needLeft) needLeft++;
        if (excessRight < needLeft) needLeft -= excessRight;
        else needLeft = 0;

        //printf("%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 "\n", needLeft, excessRight, index, treapPtr->key.cost);

        if ((treapPtr->value == 0) && (excessRight == 0) && (needLeft == index+1)) return treapPtr->key;
        if (index >= needLeft) index -= needLeft, treapPtr = treapPtr->right;
        else treapPtr = treapPtr->left;
    }
}

typedef int64_t num_dishes;
typedef int64_t num_pupils;
typedef int64_t cost;
typedef int64_t num_queries;

num_dishes numDishes;
num_pupils numPupils;
num_queries numQueries;
cost dishes[300010], pupils[300010];
struct treap *dishesAndPupils;

num_dishes i;
num_pupils j, queryIndex;
item_key storeKey;
cost queryCost;
num_queries queryType;

int main() {
    scanf("%" PRId64 " %" PRId64, &numDishes, &numPupils);
    REPEAT(i, numDishes) {
        scanf("%" PRId64, dishes+i);

        storeKey.cost = dishes[i];
        storeKey.index = i;
        addElementByKey(&dishesAndPupils, storeKey, 0, false);
    }
    REPEAT(i, numPupils) {
        scanf("%" PRId64, pupils+i);

        storeKey.cost = pupils[i];
        storeKey.index = i+numDishes;
        addElementByKey(&dishesAndPupils, storeKey, 1, false);
    }

    scanf("%" PRId64, &numQueries);
    while (numQueries--) {
        scanf("%" PRId64 " %" PRId64 " %" PRId64, &queryType, &queryIndex, &queryCost);
        queryIndex--;
        storeKey.cost = (queryType == 1) ? dishes[queryIndex] : pupils[queryIndex];
        storeKey.index = (queryType == 1) ? queryIndex : (queryIndex+numDishes);
        bool success = removeElementByKey(&dishesAndPupils, storeKey);
        if (!success) puts("NOES"), exit(1);

        storeKey.cost = queryCost;
        if (queryType == 1) dishes[queryIndex] = queryCost;
        else pupils[queryIndex] = queryCost;
        addElementByKey(&dishesAndPupils, storeKey, (queryType == 2), false);
        //printf("%" PRId64 "\n", getTreapNeed(dishesAndPupils));

        if (getTreapNeed(dishesAndPupils) > 0) printf("%" PRId64 "\n", getHighestNeed(dishesAndPupils).cost);
        else puts("-1");
    }

    exit(0);
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdbool>
#include <cinttypes>

#define REPEAT(token, num) for (token = 0; token < num; token++)
static inline int64_t min(int64_t length1, int64_t length2) { return (length1 < length2) ? length1 : length2; }
static inline int64_t max(int64_t length1, int64_t length2) { return (length1 > length2) ? length1 : length2; }

//#define DEBUG
#ifdef DEBUG
#define PRINTF printf
#else
#define PRINTF(...)
#endif

typedef int64_t num_items;

namespace treap {
    template <class item_key, class item_value> struct treap;

    template <class item_key, class item_value> struct node {
        item_key key;
        item_value value;
        num_items priority;
        num_items size;
        num_items need;
        num_items excess;
        treap<item_key, item_value> left;
        treap<item_key, item_value> right;
    };

    template <class item_key, class item_value> struct treap_pair {
        treap<item_key, item_value> left;
        treap<item_key, item_value> right;
        treap_pair() : left(nullptr), right(nullptr) {};
    };

    template <class item_key, class item_value> static treap<item_key, item_value> newTreapNode(item_key key, item_value value);

    template <class item_key, class item_value> struct treap {
        node<item_key, item_value> *root;
        treap() { root = nullptr; }
        treap(node<item_key, item_value> *ptr) { root = ptr; }

        num_items getSize() { return (root == nullptr) ? 0 : root->size; }
        num_items getNeed() { return (root == nullptr) ? 0 : root->need; }
        num_items getExcess() { return (root == nullptr) ? 0 : root->excess; }
        void updateProperties() {
            if (root != nullptr) {
                root->size = 1+root->left.getSize()+root->right.getSize();
                num_items needLeft = root->left.getNeed();
                num_items excessRight = root->right.getExcess();
                if (root->value > 0) excessRight++;
                else needLeft++;

                num_items nodesMatched = needLeft;
                if (excessRight < nodesMatched) nodesMatched = excessRight;

                root->need = needLeft+root->right.getNeed()-nodesMatched;
                root->excess = root->left.getExcess()+excessRight-nodesMatched;
            }
        }

        static treap<item_key, item_value> mergeTreaps(treap<item_key, item_value> left, treap<item_key, item_value> right) {
            if (left.root == nullptr) return right;
            if (right.root == nullptr) return left;
            if (left.root->priority > right.root->priority) {
                left.root->right = mergeTreaps(left.root->right, right);
                left.updateProperties();
                return left;
            } else {
                right.root->left = mergeTreaps(left, right.root->left);
                right.updateProperties();
                return right;
            }
        }

        //Split treap into a left-side with all elements less than or equal to key and a right-side with the rest of the elements.
        //Note that if exclusive is true, then left-side will have all elements less than key and right-side will have all elements greater than or equal to key.
        treap_pair<item_key, item_value> splitByKey(item_key key, bool exclusive) {
            treap_pair<item_key, item_value> answer;
            if (root == nullptr) return answer;

            //If the key is less than the key of the root, then all items less than or equal to key are on the left-hand side.
            if (exclusive ? (key <= root->key) : (key < root->key)) {
                answer = root->left.splitByKey(key, exclusive);
                //Since answer.left is the tree rooted at key, make answer.right, which has all elements greater than key but less than the key of the root, the new left node of the treap:
                root->left = answer.right;
                //After making this modification, this becomes the right-side, which has all elements greater than key:
                answer.right = *this;
            }
            //If the key is greater than or equal to the key of the root, then we know that the left-side and the root is composed of all elements less than or equal to key, so we need to search the right-hand side for any other elements which are less than or equal to key.
            else {
                answer = root->right.splitByKey(key, exclusive);
                //Now, we need to combine this treap and its left-side with all of the elements in the right-side which are also less than or equal to key.
                //These elements are now in answer.left, so make answer.left the new right-side of treap:
                root->right = answer.left;
                //After making this modification, this becomes the left-side, which has all elements less than or equal to key:
                answer.left = *this;
            }
            updateProperties();
            return answer;
        }

        item_value getKeyRangeSum(item_key startKey, item_key endKey) {
            //Split the treap up into a left-side which has all elements up to endKey:
            treap_pair<item_key, item_value> parts = splitByKey(endKey, false);
            //Split that treap up into a left-side which has all elements up to startKey-1:
            treap_pair<item_key, item_value> parts2 = parts.left.splitByKey(startKey, true);
            //Get the sum of the elements greater than startKey, less than or equal to endKey:
            item_value result = parts2.right.getSum();
            //Merge the treaps back together:
            root = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right).root;
            return result;
        }

        bool addElementByKey(item_key newKey, item_value newValue, bool exclusive) {
            //Split treap up into a left-side with all elements less than newKey:
            treap_pair<item_key, item_value> parts = splitByKey(newKey, false);
            //Make sure newKey is not already in the tree:
            if (exclusive) {
                treap_pair<item_key, item_value> parts2 = parts.left.splitByKey(newKey, true);
                if (parts2.right.root != nullptr) {
                    root = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right).root;
                    return false;
                }
                parts.left = mergeTreaps(parts2.left, parts2.right);
            }

            //Create a new node:
            treap<item_key, item_value> storeTreap = newTreapNode<item_key, item_value>(newKey, newValue);
            //Put the new node to the right of the left-side, and then merge the new left-side with the right-side:
            root = mergeTreaps(mergeTreaps(parts.left, storeTreap), parts.right).root;

            return true;
        }

        bool removeElementByKey(item_key oldKey) {
            //Split treap up into a left-side which has all elements up to oldKey:
            treap_pair<item_key, item_value> parts = splitByKey(oldKey, false);
            //Now, split the left-side up into a left-side which has all elements before oldKey and a right-side which has all elements equal to oldKey:
            treap_pair<item_key, item_value> parts2 = parts.left.splitByKey(oldKey, true);
            //Record whether there were actually any elements with oldKey:
            bool actuallyRemoved = parts2.right.root != nullptr;
            //Merge treaps back together without the elements equal to oldKey:
            root = mergeTreaps(parts2.left, parts.right).root;

            return actuallyRemoved;
        }

        //Split treap into a left-side with the first pos elements and a right-side with the rest of the elements.
        //The left-side will be rooted with the (pos-1)th item (0-based indexing), if it exists.
        treap_pair<item_key, item_value> splitByPos(num_items pos) {
            treap_pair<item_key, item_value> answer;
            if (this->root == nullptr) return answer;
            if (pos > getSize()) {
                answer.left = *this;
                return answer;
            }

            num_items leftSize = root->left.getSize();
            //If the left-side has pos elements or more, then the (pos-1)th element is on the left-side:
            if (pos <= leftSize) {
                answer = root->left.splitByPos(pos);
                //Since answer.left is the tree rooted at (pos-1)th element, make answer.right, the elements between the (pos-1)th element and the root, the new left node of the treap:
                root->left = answer.right;
                //After making this modification, treap1 becomes the right-side, which has all elements after the (pos-1)th one:
                answer.right = *this;
            }
            //Otherwise, we need to split the right-side up to look for the (pos-1)th element:
            else {
                //Notice that we subtract pos by the number of elements in the root and left-side:
                answer = root->right.splitByPos(pos-leftSize-1);
                //Now, in order to get all of the first pos elements, we need to combine treap1 and its left-side with all of the elements in the right-side.
                //These elements are now in answer.left, so make answer.left the new right-side of treap:
                root->right = answer.left;
                //After making this modification, treap1 becomes the left-side, which has all of the first pos elements:
                answer.left = *this;
            }
            updateProperties();
            return answer;
        }

        item_value getIntervalSum(num_items startPos, num_items endPos) {
            //Split the treap up into a left-side which has all elements up to endPos index:
            treap_pair<item_key, item_value> parts = splitByPos(endPos+1);
            //Split that treap up into a left-side which has all elements up to startPos-1 index:
            treap_pair<item_key, item_value> parts2 = parts.left.splitByPos(startPos);
            //Get the sum of the elements with index greater than startPos-1, less than or equal to endPos:
            item_value result = parts2.right.getSum();
            //Merge the treaps back together:
            root = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right).root;
            return result;
        }

        void addElementByPos(num_items newPos, item_key newKey, item_value newValue) {
            //Split treap up into a left-side with first pos elements:
            treap_pair<item_key, item_value> parts = splitByPos(newPos);
            //Create the new node:
            treap<item_key, item_value> storeTreap = newTreapNode<item_key, item_value>(newKey, newValue);
            //Put the new node to the right of the left-side, and then merge the new left-side with the right-side:
            root = mergeTreaps(mergeTreaps(parts.left, storeTreap), parts.right).root;
        }

        bool removeElementByPos(num_items oldPos) {
            //If the index is too big or too small, we can't remove it:
            if (oldPos+1 > getSize()) return false;
            if (oldPos < 0) return false;

            //Split treap up into a left-side which has the first (oldPos+1) elements:
            treap_pair<item_key, item_value> parts = splitByPos(oldPos+1);
            //Now, separate out the first oldPos elements from this left-side in order to isolate the (oldPos)th element:
            treap_pair<item_key, item_value> parts2 = parts.left.splitByPos(oldPos);
            //Merge treaps back together without the isolated element:
            root = mergeTreaps(parts2.left, parts.right).root;

            return true;
        }

        item_value *getValueAtPos(num_items pos) {
            //If the index is too big or too small, we can't find its value:
            if (pos < 0) return nullptr;
            if (pos > getSize()) return nullptr;

            treap<item_key, item_value> curTreap = *this;
            //Keep looking for the treap whose root is the (pos)th element:
            while (curTreap.root->left.size() != pos) {
                //If the left subtree has less than pos elements, then the (pos)th element must be in the right subtree.
                //Also, adjust pos accordingly.
                if (curTreap.root->left.size() < pos) {
                    pos -= curTreap.root->left.size()+1;
                    curTreap = curTreap.root->right;
                }
                //Otherwise, the (pos)th element must be in the left subtree.
                else curTreap = curTreap.root->left;

                if (curTreap.root == nullptr) puts("Treap size values are corrupted"), exit(1);
            }
            //Finally, return the value of the root element:
            return &(curTreap.root->value);
        }

        item_key getHighestNeed() {
            num_items index = getNeed()-1;
            treap<item_key, item_value> curTreap = *this;

            while (true) {
                num_items needLeft = curTreap.root->left.getNeed();
                num_items excessRight = curTreap.root->right.getExcess();
                if (curTreap.root->value > 0) excessRight++;
                else if (excessRight <= needLeft) needLeft++;
                if (excessRight < needLeft) needLeft -= excessRight;
                else needLeft = 0;

                if ((curTreap.root->value == 0) && (excessRight == 0) && (needLeft == index+1)) return curTreap.root->key;
                if (index >= needLeft) index -= needLeft, curTreap = curTreap.root->right;
                else curTreap = curTreap.root->left;
            }
        }
    };

    static const num_items MAX_SPACE = 4000000;
    template <class item_key, class item_value> static node<item_key, item_value> space[MAX_SPACE];
    template <class item_key, class item_value> static num_items numSpaceUsed;
    template <class item_key, class item_value> static treap<item_key, item_value> newTreapNode(item_key key, item_value value) {
        if (numSpaceUsed<item_key, item_value> >= MAX_SPACE) puts("Ran out of treap node space"), exit(1);

        space<item_key, item_value>[numSpaceUsed<item_key, item_value>].priority = rand();
        space<item_key, item_value>[numSpaceUsed<item_key, item_value>].key = key;
        space<item_key, item_value>[numSpaceUsed<item_key, item_value>].value = value;
        space<item_key, item_value>[numSpaceUsed<item_key, item_value>].left = treap<item_key, item_value>();
        space<item_key, item_value>[numSpaceUsed<item_key, item_value>].right = treap<item_key, item_value>();

        treap<item_key, item_value> newNode(space<item_key, item_value>+numSpaceUsed<item_key, item_value>);
        newNode.updateProperties();

        numSpaceUsed<item_key, item_value>++;
        return newNode;
    }
}

struct item_key {
    int64_t cost;
    int64_t index;

    bool operator<(item_key other) {
        if (cost != other.cost) return cost < other.cost;
        return index < other.index;
    }
    bool operator<=(item_key other) {
        if (cost != other.cost) return cost <= other.cost;
        return index <= other.index;
    }
};
typedef int64_t item_value;
typedef int64_t num_items;

typedef int64_t num_dishes;
typedef int64_t num_pupils;
typedef int64_t cost;
typedef int64_t num_queries;

num_dishes numDishes;
num_pupils numPupils;
num_queries numQueries;
cost dishes[300010], pupils[300010];
treap::treap<item_key, item_value> dishesAndPupils;

num_dishes i;
num_pupils j, queryIndex;
item_key storeKey;
cost queryCost;
num_queries queryType;

int main() {
    scanf("%" PRId64 " %" PRId64, &numDishes, &numPupils);
    REPEAT(i, numDishes) {
        scanf("%" PRId64, dishes+i);

        storeKey.cost = dishes[i];
        storeKey.index = i;
        //addElementByKey(&dishesAndPupils, storeKey, 0, false);
        dishesAndPupils.addElementByKey(storeKey, 0, false);
    }
    REPEAT(i, numPupils) {
        scanf("%" PRId64, pupils+i);

        storeKey.cost = pupils[i];
        storeKey.index = i+numDishes;
        //addElementByKey(&dishesAndPupils, storeKey, 1, false);
        dishesAndPupils.addElementByKey(storeKey, 1, false);
    }

    scanf("%" PRId64, &numQueries);
    while (numQueries--) {
        scanf("%" PRId64 " %" PRId64 " %" PRId64, &queryType, &queryIndex, &queryCost);
        queryIndex--;
        storeKey.cost = (queryType == 1) ? dishes[queryIndex] : pupils[queryIndex];
        storeKey.index = (queryType == 1) ? queryIndex : (queryIndex+numDishes);
        bool success = dishesAndPupils.removeElementByKey(storeKey);
        if (!success) puts("NOES"), exit(1);

        storeKey.cost = queryCost;
        if (queryType == 1) dishes[queryIndex] = queryCost;
        else pupils[queryIndex] = queryCost;
        dishesAndPupils.addElementByKey(storeKey, (queryType == 2), false);
        //printf("D %" PRId64 "\n", dishesAndPupils.getNeed());

        if (dishesAndPupils.getNeed() > 0) printf("%" PRId64 "\n", dishesAndPupils.getHighestNeed().cost);
        else puts("-1");
    }

    exit(0);
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdbool>
#include <cinttypes>

#define REPEAT(token, num) for (token = 0; token < num; token++)
static inline int64_t min(int64_t length1, int64_t length2) { return (length1 < length2) ? length1 : length2; }
static inline int64_t max(int64_t length1, int64_t length2) { return (length1 > length2) ? length1 : length2; }

//#define DEBUG
#ifdef DEBUG
#define PRINTF printf
#else
#define PRINTF(...)
#endif

typedef int32_t num_items;

namespace treap {
    template <class item_key, class item_value> struct treap;

    template <class item_key, class item_value> struct node {
        item_key key;
        item_value value;
        num_items priority;
        num_items size;
        num_items need;
        num_items excess;
        treap<item_key, item_value> left;
        treap<item_key, item_value> right;
    };

    template <class item_key, class item_value> struct treap_pair {
        treap<item_key, item_value> left;
        treap<item_key, item_value> right;
        treap_pair() : left(nullptr), right(nullptr) {};
    };

    template <class item_key, class item_value> struct node_manager;

    template <class item_key, class item_value> struct treap {
        node<item_key, item_value> *root;
        treap() { root = nullptr; }
        treap(node<item_key, item_value> *ptr) { root = ptr; }

        num_items getSize() { return (root == nullptr) ? 0 : root->size; }
        num_items getNeed() { return (root == nullptr) ? 0 : root->need; }
        num_items getExcess() { return (root == nullptr) ? 0 : root->excess; }
        void updateProperties() {
            if (root != nullptr) {
                root->size = 1+root->left.getSize()+root->right.getSize();
                num_items needLeft = root->left.getNeed();
                num_items excessRight = root->right.getExcess();
                if (root->value > 0) excessRight++;
                else needLeft++;

                num_items nodesMatched = needLeft;
                if (excessRight < nodesMatched) nodesMatched = excessRight;

                root->need = needLeft+root->right.getNeed()-nodesMatched;
                root->excess = root->left.getExcess()+excessRight-nodesMatched;
            }
        }

        static treap<item_key, item_value> mergeTreaps(treap<item_key, item_value> left, treap<item_key, item_value> right) {
            if (left.root == nullptr) return right;
            if (right.root == nullptr) return left;
            if (left.root->priority > right.root->priority) {
                left.root->right = mergeTreaps(left.root->right, right);
                left.updateProperties();
                return left;
            } else {
                right.root->left = mergeTreaps(left, right.root->left);
                right.updateProperties();
                return right;
            }
        }

        //Split treap into a left-side with all elements less than or equal to key and a right-side with the rest of the elements.
        //Note that if exclusive is true, then left-side will have all elements less than key and right-side will have all elements greater than or equal to key.
        treap_pair<item_key, item_value> splitByKey(item_key key, bool exclusive) {
            treap_pair<item_key, item_value> answer;
            if (root == nullptr) return answer;

            //If the key is less than the key of the root, then all items less than or equal to key are on the left-hand side.
            if (exclusive ? (key <= root->key) : (key < root->key)) {
                answer = root->left.splitByKey(key, exclusive);
                //Since answer.left is the tree rooted at key, make answer.right, which has all elements greater than key but less than the key of the root, the new left node of the treap:
                root->left = answer.right;
                //After making this modification, this becomes the right-side, which has all elements greater than key:
                answer.right = *this;
            }
            //If the key is greater than or equal to the key of the root, then we know that the left-side and the root is composed of all elements less than or equal to key, so we need to search the right-hand side for any other elements which are less than or equal to key.
            else {
                answer = root->right.splitByKey(key, exclusive);
                //Now, we need to combine this treap and its left-side with all of the elements in the right-side which are also less than or equal to key.
                //These elements are now in answer.left, so make answer.left the new right-side of treap:
                root->right = answer.left;
                //After making this modification, this becomes the left-side, which has all elements less than or equal to key:
                answer.left = *this;
            }
            updateProperties();
            return answer;
        }

        item_value getKeyRangeSum(item_key startKey, item_key endKey) {
            //Split the treap up into a left-side which has all elements up to endKey:
            treap_pair<item_key, item_value> parts = splitByKey(endKey, false);
            //Split that treap up into a left-side which has all elements up to startKey-1:
            treap_pair<item_key, item_value> parts2 = parts.left.splitByKey(startKey, true);
            //Get the sum of the elements greater than startKey, less than or equal to endKey:
            item_value result = parts2.right.getSum();
            //Merge the treaps back together:
            root = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right).root;
            return result;
        }

        bool addElementByKey(item_key newKey, item_value newValue, bool exclusive) {
            //Split treap up into a left-side with all elements less than newKey:
            treap_pair<item_key, item_value> parts = splitByKey(newKey, false);
            //Make sure newKey is not already in the tree:
            if (exclusive) {
                treap_pair<item_key, item_value> parts2 = parts.left.splitByKey(newKey, true);
                if (parts2.right.root != nullptr) {
                    root = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right).root;
                    return false;
                }
                parts.left = mergeTreaps(parts2.left, parts2.right);
            }

            //Create a new node:
            treap<item_key, item_value> storeTreap = node_manager<item_key, item_value>::newTreapNode(newKey, newValue);
            //Put the new node to the right of the left-side, and then merge the new left-side with the right-side:
            root = mergeTreaps(mergeTreaps(parts.left, storeTreap), parts.right).root;

            return true;
        }

        bool removeElementByKey(item_key oldKey) {
            //Split treap up into a left-side which has all elements up to oldKey:
            treap_pair<item_key, item_value> parts = splitByKey(oldKey, false);
            //Now, split the left-side up into a left-side which has all elements before oldKey and a right-side which has all elements equal to oldKey:
            treap_pair<item_key, item_value> parts2 = parts.left.splitByKey(oldKey, true);
            //Record whether there were actually any elements with oldKey:
            bool actuallyRemoved = parts2.right.root != nullptr;
            //Merge treaps back together without the elements equal to oldKey:
            root = mergeTreaps(parts2.left, parts.right).root;

            return actuallyRemoved;
        }

        //Split treap into a left-side with the first pos elements and a right-side with the rest of the elements.
        //The left-side will be rooted with the (pos-1)th item (0-based indexing), if it exists.
        treap_pair<item_key, item_value> splitByPos(num_items pos) {
            treap_pair<item_key, item_value> answer;
            if (this->root == nullptr) return answer;
            if (pos > getSize()) {
                answer.left = *this;
                return answer;
            }

            num_items leftSize = root->left.getSize();
            //If the left-side has pos elements or more, then the (pos-1)th element is on the left-side:
            if (pos <= leftSize) {
                answer = root->left.splitByPos(pos);
                //Since answer.left is the tree rooted at (pos-1)th element, make answer.right, the elements between the (pos-1)th element and the root, the new left node of the treap:
                root->left = answer.right;
                //After making this modification, treap1 becomes the right-side, which has all elements after the (pos-1)th one:
                answer.right = *this;
            }
            //Otherwise, we need to split the right-side up to look for the (pos-1)th element:
            else {
                //Notice that we subtract pos by the number of elements in the root and left-side:
                answer = root->right.splitByPos(pos-leftSize-1);
                //Now, in order to get all of the first pos elements, we need to combine treap1 and its left-side with all of the elements in the right-side.
                //These elements are now in answer.left, so make answer.left the new right-side of treap:
                root->right = answer.left;
                //After making this modification, treap1 becomes the left-side, which has all of the first pos elements:
                answer.left = *this;
            }
            updateProperties();
            return answer;
        }

        item_value getIntervalSum(num_items startPos, num_items endPos) {
            //Split the treap up into a left-side which has all elements up to endPos index:
            treap_pair<item_key, item_value> parts = splitByPos(endPos+1);
            //Split that treap up into a left-side which has all elements up to startPos-1 index:
            treap_pair<item_key, item_value> parts2 = parts.left.splitByPos(startPos);
            //Get the sum of the elements with index greater than startPos-1, less than or equal to endPos:
            item_value result = parts2.right.getSum();
            //Merge the treaps back together:
            root = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right).root;
            return result;
        }

        void addElementByPos(num_items newPos, item_key newKey, item_value newValue) {
            //Split treap up into a left-side with first pos elements:
            treap_pair<item_key, item_value> parts = splitByPos(newPos);
            //Create the new node:
            treap<item_key, item_value> storeTreap = node_manager<item_key, item_value>::newTreapNode(newKey, newValue);
            //Put the new node to the right of the left-side, and then merge the new left-side with the right-side:
            root = mergeTreaps(mergeTreaps(parts.left, storeTreap), parts.right).root;
        }

        bool removeElementByPos(num_items oldPos) {
            //If the index is too big or too small, we can't remove it:
            if (oldPos+1 > getSize()) return false;
            if (oldPos < 0) return false;

            //Split treap up into a left-side which has the first (oldPos+1) elements:
            treap_pair<item_key, item_value> parts = splitByPos(oldPos+1);
            //Now, separate out the first oldPos elements from this left-side in order to isolate the (oldPos)th element:
            treap_pair<item_key, item_value> parts2 = parts.left.splitByPos(oldPos);
            //Merge treaps back together without the isolated element:
            root = mergeTreaps(parts2.left, parts.right).root;

            return true;
        }

        item_value *getValueAtPos(num_items pos) {
            //If the index is too big or too small, we can't find its value:
            if (pos < 0) return nullptr;
            if (pos > getSize()) return nullptr;

            treap<item_key, item_value> curTreap = *this;
            //Keep looking for the treap whose root is the (pos)th element:
            while (curTreap.root->left.size() != pos) {
                //If the left subtree has less than pos elements, then the (pos)th element must be in the right subtree.
                //Also, adjust pos accordingly.
                if (curTreap.root->left.size() < pos) {
                    pos -= curTreap.root->left.size()+1;
                    curTreap = curTreap.root->right;
                }
                //Otherwise, the (pos)th element must be in the left subtree.
                else curTreap = curTreap.root->left;

                if (curTreap.root == nullptr) puts("Treap size values are corrupted"), exit(1);
            }
            //Finally, return the value of the root element:
            return &(curTreap.root->value);
        }

        item_key getHighestNeed() {
            num_items index = getNeed()-1;
            treap<item_key, item_value> curTreap = *this;

            while (true) {
                num_items needLeft = curTreap.root->left.getNeed();
                num_items excessRight = curTreap.root->right.getExcess();
                if (curTreap.root->value > 0) excessRight++;
                else if (excessRight <= needLeft) needLeft++;
                if (excessRight < needLeft) needLeft -= excessRight;
                else needLeft = 0;

                if ((curTreap.root->value == 0) && (excessRight == 0) && (needLeft == index+1)) return curTreap.root->key;
                if (index >= needLeft) index -= needLeft, curTreap = curTreap.root->right;
                else curTreap = curTreap.root->left;
            }
        }
    };

    template <class item_key, class item_value> struct node_manager {
        static const num_items MAX_SPACE = 900010;
        static node<item_key, item_value> space[MAX_SPACE];
        static num_items numSpaceUsed;
        static treap<item_key, item_value> newTreapNode(item_key key, item_value value) {
            if (numSpaceUsed >= MAX_SPACE) puts("Ran out of treap node space"), exit(1);

            space[numSpaceUsed].priority = rand();
            space[numSpaceUsed].key = key;
            space[numSpaceUsed].value = value;
            space[numSpaceUsed].left = treap<item_key, item_value>();
            space[numSpaceUsed].right = treap<item_key, item_value>();

            treap<item_key, item_value> newNode(space+numSpaceUsed);
            newNode.updateProperties();

            numSpaceUsed++;
            return newNode;
        }
    };
}
template <class item_key, class item_value> treap::node<item_key, item_value> treap::node_manager<item_key, item_value>::space[MAX_SPACE];
template <class item_key, class item_value> num_items treap::node_manager<item_key, item_value>::numSpaceUsed;

struct item_key {
    int32_t cost;
    int32_t index;

    bool operator<(item_key other) {
        if (cost != other.cost) return cost < other.cost;
        return index < other.index;
    }
    bool operator<=(item_key other) {
        if (cost != other.cost) return cost <= other.cost;
        return index <= other.index;
    }
};
typedef int32_t item_value;
typedef int32_t num_items;

typedef int32_t num_dishes;
typedef int32_t num_pupils;
typedef int32_t cost;
typedef int32_t num_queries;

num_dishes numDishes;
num_pupils numPupils;
num_queries numQueries;
cost dishes[300010], pupils[300010];
treap::treap<item_key, item_value> dishesAndPupils;

num_dishes i;
num_pupils j, queryIndex;
item_key storeKey;
cost queryCost;
num_queries queryType;

int main() {
    scanf("%" PRId32 " %" PRId32, &numDishes, &numPupils);
    REPEAT(i, numDishes) {
        scanf("%" PRId32, dishes+i);

        storeKey.cost = dishes[i];
        storeKey.index = i;
        //addElementByKey(&dishesAndPupils, storeKey, 0, false);
        dishesAndPupils.addElementByKey(storeKey, 0, false);
    }
    REPEAT(i, numPupils) {
        scanf("%" PRId32, pupils+i);

        storeKey.cost = pupils[i];
        storeKey.index = i+numDishes;
        //addElementByKey(&dishesAndPupils, storeKey, 1, false);
        dishesAndPupils.addElementByKey(storeKey, 1, false);
    }

    scanf("%" PRId32, &numQueries);
    while (numQueries--) {
        scanf("%" PRId32 " %" PRId32 " %" PRId32, &queryType, &queryIndex, &queryCost);
        queryIndex--;
        storeKey.cost = (queryType == 1) ? dishes[queryIndex] : pupils[queryIndex];
        storeKey.index = (queryType == 1) ? queryIndex : (queryIndex+numDishes);
        bool success = dishesAndPupils.removeElementByKey(storeKey);
        if (!success) puts("NOES"), exit(1);

        storeKey.cost = queryCost;
        if (queryType == 1) dishes[queryIndex] = queryCost;
        else pupils[queryIndex] = queryCost;
        dishesAndPupils.addElementByKey(storeKey, (queryType == 2), false);
        //printf("D %" PRId64 "\n", dishesAndPupils.getNeed());

        if (dishesAndPupils.getNeed() > 0) printf("%" PRId32 "\n", dishesAndPupils.getHighestNeed().cost);
        else puts("-1");
    }

    exit(0);
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdbool>
#include <cinttypes>

#define REPEAT(token, num) for (token = 0; token < num; token++)
static inline int64_t min(int64_t length1, int64_t length2) { return (length1 < length2) ? length1 : length2; }
static inline int64_t max(int64_t length1, int64_t length2) { return (length1 > length2) ? length1 : length2; }

//#define DEBUG
#ifdef DEBUG
#define PRINTF printf
#else
#define PRINTF(...)
#endif

typedef struct {
    int64_t cost;
    int64_t index;
} item_key;
typedef int64_t item_value;
typedef int64_t num_items;

int64_t compareKeys(item_key key1, item_key key2) {
    if (key1.cost != key2.cost) return key1.cost-key2.cost;
    return key1.index-key2.index;
}

struct treap {
    item_key key;
    item_value value;
    num_items priority;
    num_items size;
    num_items need;
    num_items excess;
    struct treap *left;
    struct treap *right;
};
struct treap_pair {
    struct treap *left;
    struct treap *right;
};

struct treap space[9000010];
num_items numSpaceUsed;

num_items getTreapSize(struct treap *treap1) {
    if (treap1 == NULL) return 0;
    return treap1->size;
}

num_items getTreapNeed(struct treap *treap1) {
    if (treap1 == NULL) return 0;
    return treap1->need;
}

num_items getTreapExcess(struct treap *treap1) {
    if (treap1 == NULL) return 0;
    return treap1->excess;
}

void calcTreapProperties(struct treap *treap1) {
    if (treap1 != NULL) {
        treap1->size = 1+getTreapSize(treap1->left)+getTreapSize(treap1->right);

        num_items needLeft = getTreapNeed(treap1->left);
        num_items excessRight = getTreapExcess(treap1->right);
        if (treap1->value > 0) excessRight++;
        else needLeft++;

        num_items nodesMatched = needLeft;
        if (excessRight < nodesMatched) nodesMatched = excessRight;

        treap1->need = needLeft+getTreapNeed(treap1->right)-nodesMatched;
        treap1->excess = getTreapExcess(treap1->left)+excessRight-nodesMatched;
    }
}

struct treap *newTreap(item_key key, item_value value) {
    if (numSpaceUsed >= 9000010) fprintf(stderr, "Ran out of treap space"), exit(1);
    space[numSpaceUsed].priority = rand();
    space[numSpaceUsed].key = key;
    space[numSpaceUsed].value = value;
    space[numSpaceUsed].left = NULL;
    space[numSpaceUsed].right = NULL;
    calcTreapProperties(space+numSpaceUsed);
    numSpaceUsed++;
    return space+(numSpaceUsed-1);
}

struct treap *mergeTreaps(struct treap *left, struct treap *right) {
    if (left == NULL) return right;
    if (right == NULL) return left;
    if (left->priority > right->priority) {
        left->right = mergeTreaps(left->right, right);
        calcTreapProperties(left);
        return left;
    } else {
        right->left = mergeTreaps(left, right->left);
        calcTreapProperties(right);
        return right;
    }
}

//Split treap into a left-side with all elements less than or equal to key and a right-side with the rest of the elements.
//Note that if exclusive is true, then left-side will have all elements less than key and right-side will have all elements greater than or equal to key.
struct treap_pair splitByKey(struct treap *treap1, item_key key, bool exclusive) {
    struct treap_pair answer;
    if (treap1 == NULL) {
        answer.left = answer.right = NULL;
        return answer;
    }

    int compareKeysResult = compareKeys(key, treap1->key);
    //If the key is less than the key of the root, then all items less than or equal to key are on the left-hand side.
    if (exclusive ? (compareKeysResult <= 0) : (compareKeysResult < 0)) {
        answer = splitByKey(treap1->left, key, exclusive);
        //Since answer.left is the tree rooted at key, make answer.right, which has all elements greater than key but less than the key of the root, the new left node of the treap:
        treap1->left = answer.right;
        //After making this modification, treap1 becomes the right-side, which has all elements greater than key:
        answer.right = treap1;
    }
    //If the key is greater than or equal to the key of the root, then we know that the left-side and the root is composed of all elements less than or equal to key, so we need to search the right-hand side for any other elements which are less than or equal to key.
    else {
        answer = splitByKey(treap1->right, key, exclusive);
        //Now, we need to combine treap1 and its left-side with all of the elements in the right-side which are also less than or equal to key.
        //These elements are now in answer.left, so make answer.left the new right-side of treap:
        treap1->right = answer.left;
        //After making this modification, treap1 becomes the left-side, which has all elements less than or equal to key:
        answer.left = treap1;
    }
    calcTreapProperties(treap1);
    return answer;
}

bool addElementByKey(struct treap **treapPtr, item_key newKey, item_value newValue, bool exclusive) {
    //Split treap up into a left-side with all elements less than newKey:
    struct treap_pair parts = splitByKey(*treapPtr, newKey, false);
    //Make sure newKey is not already in the tree:
    if (exclusive) {
        struct treap_pair parts2 = splitByKey(parts.left, newKey, true);
        if (parts2.right != NULL) {
            *treapPtr = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right);
            return false;
        }
        parts.left = mergeTreaps(parts2.left, parts2.right);
    }

    //Create a new node:
    struct treap *storeTreap = newTreap(newKey, newValue);
    //Put the new node to the right of the left-side, and then merge the new left-side with the right-side:
    *treapPtr = mergeTreaps(mergeTreaps(parts.left, storeTreap), parts.right);

    return true;
}

bool removeElementByKey(struct treap **treapPtr, item_key oldKey) {
    //Split treap up into a left-side which has all elements up to oldKey:
    struct treap_pair parts = splitByKey(*treapPtr, oldKey, false);
    //Now, split the left-side up into a left-side which has all elements before oldKey and a right-side which has all elements equal to oldKey:
    struct treap_pair parts2 = splitByKey(parts.left, oldKey, true);
    //Record whether there were actually any elements with oldKey:
    bool actuallyRemoved = parts2.right != NULL;
    //Merge treaps back together without the elements equal to oldKey:
    *treapPtr = mergeTreaps(parts2.left, parts.right);

    return actuallyRemoved;
}

item_key getHighestNeed(struct treap *treapPtr) {
    num_items index = getTreapNeed(treapPtr)-1;

    while (true) {
        num_items needLeft = getTreapNeed(treapPtr->left);
        num_items excessRight = getTreapExcess(treapPtr->right);
        if (treapPtr->value > 0) excessRight++;
        else if (excessRight <= needLeft) needLeft++;
        if (excessRight < needLeft) needLeft -= excessRight;
        else needLeft = 0;

        //printf("%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 "\n", needLeft, excessRight, index, treapPtr->key.cost);

        if ((treapPtr->value == 0) && (excessRight == 0) && (needLeft == index+1)) return treapPtr->key;
        if (index >= needLeft) index -= needLeft, treapPtr = treapPtr->right;
        else treapPtr = treapPtr->left;
    }
}

typedef int64_t num_dishes;
typedef int64_t num_pupils;
typedef int64_t cost;
typedef int64_t num_queries;

num_dishes numDishes;
num_pupils numPupils;
num_queries numQueries;
cost dishes[300010], pupils[300010];
struct treap *dishesAndPupils;

num_dishes i;
num_pupils j, queryIndex;
item_key storeKey;
cost queryCost;
num_queries queryType;

int main() {
    scanf("%" PRId64 " %" PRId64, &numDishes, &numPupils);
    REPEAT(i, numDishes) {
        scanf("%" PRId64, dishes+i);

        storeKey.cost = dishes[i];
        storeKey.index = i;
        addElementByKey(&dishesAndPupils, storeKey, 0, false);
    }
    REPEAT(i, numPupils) {
        scanf("%" PRId64, pupils+i);

        storeKey.cost = pupils[i];
        storeKey.index = i+numDishes;
        addElementByKey(&dishesAndPupils, storeKey, 1, false);
    }

    scanf("%" PRId64, &numQueries);
    while (numQueries--) {
        scanf("%" PRId64 " %" PRId64 " %" PRId64, &queryType, &queryIndex, &queryCost);
        queryIndex--;
        storeKey.cost = (queryType == 1) ? dishes[queryIndex] : pupils[queryIndex];
        storeKey.index = (queryType == 1) ? queryIndex : (queryIndex+numDishes);
        bool success = removeElementByKey(&dishesAndPupils, storeKey);
        if (!success) puts("NOES"), exit(1);

        storeKey.cost = queryCost;
        if (queryType == 1) dishes[queryIndex] = queryCost;
        else pupils[queryIndex] = queryCost;
        addElementByKey(&dishesAndPupils, storeKey, (queryType == 2), false);
        //printf("%" PRId64 "\n", getTreapNeed(dishesAndPupils));

        if (getTreapNeed(dishesAndPupils) > 0) printf("%" PRId64 "\n", getHighestNeed(dishesAndPupils).cost);
        else puts("-1");
    }

    exit(0);
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdbool>
#include <cinttypes>

#define REPEAT(token, num) for (token = 0; token < num; token++)
static inline int64_t min(int64_t length1, int64_t length2) { return (length1 < length2) ? length1 : length2; }
static inline int64_t max(int64_t length1, int64_t length2) { return (length1 > length2) ? length1 : length2; }

//#define DEBUG
#ifdef DEBUG
#define PRINTF printf
#else
#define PRINTF(...)
#endif

typedef struct {
    int64_t cost;
    int64_t index;
} item_key;
typedef int64_t item_value;
typedef int64_t num_items;

int64_t compareKeys(item_key key1, item_key key2) {
    if (key1.cost != key2.cost) return key1.cost-key2.cost;
    return key1.index-key2.index;
}

struct treap {
    item_key key;
    item_value value;
    num_items priority;
    num_items size;
    num_items need;
    num_items excess;
    struct treap *left;
    struct treap *right;
};
struct treap_pair {
    struct treap *left;
    struct treap *right;
};

struct treap space[1000000];
num_items numSpaceUsed;

num_items getTreapSize(struct treap *treap1) {
    if (treap1 == NULL) return 0;
    return treap1->size;
}

num_items getTreapNeed(struct treap *treap1) {
    if (treap1 == NULL) return 0;
    return treap1->need;
}

num_items getTreapExcess(struct treap *treap1) {
    if (treap1 == NULL) return 0;
    return treap1->excess;
}

void calcTreapProperties(struct treap *treap1) {
    if (treap1 != NULL) {
        treap1->size = 1+getTreapSize(treap1->left)+getTreapSize(treap1->right);

        num_items needLeft = getTreapNeed(treap1->left);
        num_items excessRight = getTreapExcess(treap1->right);
        if (treap1->value > 0) excessRight++;
        else needLeft++;

        num_items nodesMatched = needLeft;
        if (excessRight < nodesMatched) nodesMatched = excessRight;

        treap1->need = needLeft+getTreapNeed(treap1->right)-nodesMatched;
        treap1->excess = getTreapExcess(treap1->left)+excessRight-nodesMatched;
    }
}

struct treap *newTreap(item_key key, item_value value) {
    if (numSpaceUsed >= 1000000) fprintf(stderr, "Ran out of treap space"), exit(1);
    space[numSpaceUsed].priority = rand();
    space[numSpaceUsed].key = key;
    space[numSpaceUsed].value = value;
    space[numSpaceUsed].left = NULL;
    space[numSpaceUsed].right = NULL;
    calcTreapProperties(space+numSpaceUsed);
    numSpaceUsed++;
    return space+(numSpaceUsed-1);
}

struct treap *mergeTreaps(struct treap *left, struct treap *right) {
    if (left == NULL) return right;
    if (right == NULL) return left;
    if (left->priority > right->priority) {
        left->right = mergeTreaps(left->right, right);
        calcTreapProperties(left);
        return left;
    } else {
        right->left = mergeTreaps(left, right->left);
        calcTreapProperties(right);
        return right;
    }
}

//Split treap into a left-side with all elements less than or equal to key and a right-side with the rest of the elements.
//Note that if exclusive is true, then left-side will have all elements less than key and right-side will have all elements greater than or equal to key.
struct treap_pair splitByKey(struct treap *treap1, item_key key, bool exclusive) {
    struct treap_pair answer;
    if (treap1 == NULL) {
        answer.left = answer.right = NULL;
        return answer;
    }

    int compareKeysResult = compareKeys(key, treap1->key);
    //If the key is less than the key of the root, then all items less than or equal to key are on the left-hand side.
    if (exclusive ? (compareKeysResult <= 0) : (compareKeysResult < 0)) {
        answer = splitByKey(treap1->left, key, exclusive);
        //Since answer.left is the tree rooted at key, make answer.right, which has all elements greater than key but less than the key of the root, the new left node of the treap:
        treap1->left = answer.right;
        //After making this modification, treap1 becomes the right-side, which has all elements greater than key:
        answer.right = treap1;
    }
    //If the key is greater than or equal to the key of the root, then we know that the left-side and the root is composed of all elements less than or equal to key, so we need to search the right-hand side for any other elements which are less than or equal to key.
    else {
        answer = splitByKey(treap1->right, key, exclusive);
        //Now, we need to combine treap1 and its left-side with all of the elements in the right-side which are also less than or equal to key.
        //These elements are now in answer.left, so make answer.left the new right-side of treap:
        treap1->right = answer.left;
        //After making this modification, treap1 becomes the left-side, which has all elements less than or equal to key:
        answer.left = treap1;
    }
    calcTreapProperties(treap1);
    return answer;
}

bool addElementByKey(struct treap **treapPtr, item_key newKey, item_value newValue, bool exclusive) {
    //Split treap up into a left-side with all elements less than newKey:
    struct treap_pair parts = splitByKey(*treapPtr, newKey, false);
    //Make sure newKey is not already in the tree:
    if (exclusive) {
        struct treap_pair parts2 = splitByKey(parts.left, newKey, true);
        if (parts2.right != NULL) {
            *treapPtr = mergeTreaps(mergeTreaps(parts2.left, parts2.right), parts.right);
            return false;
        }
        parts.left = mergeTreaps(parts2.left, parts2.right);
    }

    //Create a new node:
    struct treap *storeTreap = newTreap(newKey, newValue);
    //Put the new node to the right of the left-side, and then merge the new left-side with the right-side:
    *treapPtr = mergeTreaps(mergeTreaps(parts.left, storeTreap), parts.right);

    return true;
}

bool removeElementByKey(struct treap **treapPtr, item_key oldKey) {
    //Split treap up into a left-side which has all elements up to oldKey:
    struct treap_pair parts = splitByKey(*treapPtr, oldKey, false);
    //Now, split the left-side up into a left-side which has all elements before oldKey and a right-side which has all elements equal to oldKey:
    struct treap_pair parts2 = splitByKey(parts.left, oldKey, true);
    //Record whether there were actually any elements with oldKey:
    bool actuallyRemoved = parts2.right != NULL;
    //Merge treaps back together without the elements equal to oldKey:
    *treapPtr = mergeTreaps(parts2.left, parts.right);

    return actuallyRemoved;
}

item_key getHighestNeed(struct treap *treapPtr) {
    num_items index = getTreapNeed(treapPtr)-1;

    while (true) {
        num_items needLeft = getTreapNeed(treapPtr->left);
        num_items excessRight = getTreapExcess(treapPtr->right);
        if (treapPtr->value > 0) excessRight++;
        else if (excessRight <= needLeft) needLeft++;
        if (excessRight < needLeft) needLeft -= excessRight;
        else needLeft = 0;

        //printf("%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 "\n", needLeft, excessRight, index, treapPtr->key.cost);

        if ((treapPtr->value == 0) && (excessRight == 0) && (needLeft == index+1)) return treapPtr->key;
        if (index >= needLeft) index -= needLeft, treapPtr = treapPtr->right;
        else treapPtr = treapPtr->left;
    }
}

typedef int64_t num_dishes;
typedef int64_t num_pupils;
typedef int64_t cost;
typedef int64_t num_queries;

num_dishes numDishes;
num_pupils numPupils;
num_queries numQueries;
cost dishes[300010], pupils[300010];
struct treap *dishesAndPupils;

num_dishes i;
num_pupils j, queryIndex;
item_key storeKey;
cost queryCost;
num_queries queryType;

int main() {
    scanf("%" PRId64 " %" PRId64, &numDishes, &numPupils);
    REPEAT(i, numDishes) {
        scanf("%" PRId64, dishes+i);

        storeKey.cost = dishes[i];
        storeKey.index = i;
        addElementByKey(&dishesAndPupils, storeKey, 0, false);
    }
    REPEAT(i, numPupils) {
        scanf("%" PRId64, pupils+i);

        storeKey.cost = pupils[i];
        storeKey.index = i+numDishes;
        addElementByKey(&dishesAndPupils, storeKey, 1, false);
    }

    scanf("%" PRId64, &numQueries);
    while (numQueries--) {
        scanf("%" PRId64 " %" PRId64 " %" PRId64, &queryType, &queryIndex, &queryCost);
        queryIndex--;
        storeKey.cost = (queryType == 1) ? dishes[queryIndex] : pupils[queryIndex];
        storeKey.index = (queryType == 1) ? queryIndex : (queryIndex+numDishes);
        bool success = removeElementByKey(&dishesAndPupils, storeKey);
        if (!success) puts("NOES"), exit(1);

        storeKey.cost = queryCost;
        if (queryType == 1) dishes[queryIndex] = queryCost;
        else pupils[queryIndex] = queryCost;
        addElementByKey(&dishesAndPupils, storeKey, (queryType == 2), false);
        //printf("%" PRId64 "\n", getTreapNeed(dishesAndPupils));

        if (getTreapNeed(dishesAndPupils) > 0) printf("%" PRId64 "\n", getHighestNeed(dishesAndPupils).cost);
        else puts("-1");
    }

    exit(0);
}