#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#include<map>
#define ll long long
#define MAXN 200005
#define uns unsigned
#define INF 0x3f3f3f3f 
#define lowbit(x) ((x)&(-(x)))
#define MOD 998244353ll
using namespace std;
inline ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
	return f?x:-x;
}
int n,a[MAXN],b[MAXN],m,st[MAXN];
map<int,int>mp;
map<int,int>::iterator it;
queue<int>s[MAXN<<1];
int f[MAXN];
inline void add(int x){
	for(;x<=n;x+=lowbit(x))f[x]++;
}
inline int sum(int x){
	int res=0;
	for(;x>0;x-=lowbit(x))res+=f[x];
	return res;
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)a[i]=read()+i,mp[a[i]]++;
	for(int i=1;i<=n;i++)b[i]=read()+i,mp[b[i]]++;
	for(it=mp.begin();it!=mp.end();it++)it->second=++m;
	for(int i=1;i<=n;i++)a[i]=mp[a[i]],b[i]=mp[b[i]];
	for(int i=1;i<=n;i++)s[b[i]].push(i);
//	for(int i=1;i<=n;i++)printf("%d ",a[i]);putchar('\n');
//	for(int i=1;i<=n;i++)printf("%d ",b[i]);putchar('\n');
	bool ok=1;
	for(int i=1;i<=n;i++){
		if(s[a[i]].empty()){ok=0;break;}
		st[i]=s[a[i]].front(),s[a[i]].pop();
	}
	if(!ok)printf("-1\n");
	else{
		ll ans=0;
//		for(int i=1;i<=n;i++)printf("%d ",st[i]);putchar('\n');
		for(int i=n;i>0;i--)ans+=sum(st[i]),add(st[i]);
		printf("%lld\n",ans);
	}
	return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define BIG 200005

struct Data{
    double x;
    double y;

    bool operator<(const Data& right) const{
        return x < right.x;
    }
};

struct Dis{
    double dis;
    int i;
    int j;

    bool operator<(const Dis& right) const{
        return dis < right.dis;
    }
};

struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2

    UnionFind(int N) : par(N) { //最初は全てが根であるとして初期化
        for(int i = 0; i < N; i++) par[i] = i;
    }

    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]); // 返す値は代入される値。par[x]にルートを代入することで、次回以降、ルートへのアクセスの計算量を1にする。
    }

    bool merge(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return false; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
        return true;

    }

    bool issame(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        return root(x) == root(y);
    }
};

int main() {
    int N;
    cin >> N;
    vector<Data> al;
    for(int i=0;i<N;i++){
        Data d;
        cin >> d.x >> d.y;
        al.push_back(d);
    }
    vector<Dis> disl; // i,jの距離. N, N+1はy=-100, 100
    for(int i=0;i<N;i++){
        Data data = al[i];
        for(int j=i+1;j<N;j++){
            double dx = data.x - al[j].x;
            double dy = data.y - al[j].y;
            Dis di{sqrt(dx*dx+dy*dy), i, j};
            disl.push_back(di);
        }
        Dis d{data.y+100, i, N};
        Dis d2{100-data.y, i, N+1};
        disl.push_back(d);
        disl.push_back(d2);
    }
    sort(disl.begin(), disl.end());
    UnionFind group(N+2);
    for(int i=0;i<disl.size();i++){
        // i, jを同じグループにする
        Dis d = disl[i];
        group.merge(d.i, d.j);
        if(group.issame(N, N+1)){
            cout << setprecision(10) <<d.dis / 2.0 << endl;
            return 0;
        }
    }

    return 0;
}