//Kd Tree
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#define Nd Node*
#define To for(int i=0;i<2;i++)
#define INF 0x7f7f7f7f
#define MAXN 500000+10
using namespace std;
int D;
struct Node{
Nd l;Nd r;
int p[2],mn[2],mx[2];
}s[MAXN];
Nd root;
bool operator < (Node A,Node B){
return (A.p[D]<B.p[D]);
}
void upd(Nd A){
if(A->l)To A->mn[i]=min(A->mn[i],A->l->mn[i]),A->mx[i]=max(A->mx[i],A->l->mx[i]);
if(A->r)To A->mn[i]=min(A->mn[i],A->r->mn[i]),A->mx[i]=max(A->mx[i],A->r->mx[i]);
}
Nd NewNode(int p[2]){
Nd ret=new Node;
To ret->p[i]=ret->mn[i]=ret->mx[i]=p[i];
ret->l=ret->r=NULL;
return ret;
}
Nd Build(int L,int R,int d){
int mid=(L+R)>>1;
D=d,nth_element(s+L,s+mid,s+R+1);
Nd ret=NewNode(s[mid].p);
if(L<mid)ret->l=Build(L,mid-1,d^1);
if(mid<R)ret->r=Build(mid+1,R,d^1);
upd(ret);
return ret;
}
void build(int n){
root=Build(1,n,0);
}
int ans;
int dis(int p1[2],int p2[2]){
int ret=0;
To ret+=abs(p1[i]-p2[i]);
return ret;
}
int getdis(Nd A,int p[2]){
int ret=0;
To ret+=max(0,A->mn[i]-p[i]);
To ret+=max(0,p[i]-A->mx[i]);
return ret;
}
void Query(Nd A,int p[2]){
ans=min(ans,dis(A->p,p));
int dl=INF,dr=INF;
if(A->l)dl=getdis(A->l,p);
if(A->r)dr=getdis(A->r,p);
if(dl<dr){
if(ans>dl)Query(A->l,p);
if(ans>dr)Query(A->r,p);
}
else{
if(ans>dr)Query(A->r,p);
if(ans>dl)Query(A->l,p);
}
}
int query(int x,int y){
ans=INF;
int p[2];p[0]=x,p[1]=y;
Query(root,p);
return ans;
}
void Insert(Nd A,int d,int p[2]){
if(p[d]<A->p[d]){
if(A->l){Insert(A->l,d^1,p);}
else{A->l=NewNode(p);}
}
else{
if(A->r){Insert(A->r,d^1,p);}
else{A->r=NewNode(p);}
}
upd(A);
}
void insert(int x,int y){
int p[2];p[0]=x,p[1]=y;
Insert(root,0,p);
}
int n,m;
void init(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d%d",&s[i].p[0],&s[i].p[1]);
build(n);
}
void solve(){
int opt,x,y;
while(m--){
scanf("%d%d%d",&opt,&x,&y);
if(1==opt)insert(x,y);
else printf("%d
",query(x,y));
}
}
int main()
{
//freopen("data.in","r",stdin);
init();
solve();
return 0;
}