Problem:
Shortest Bridge
There is a city whose shape is a 1,000 $\times$ 1,000 square. The city has a big river, which flows from the north to the south and separates the city into just two parts: the west and the east.
Recently, the city mayor has decided to build a highway from a point $s$ on the west part to a point $t$ on the east part. A highway consists of a bridge on the river, and two roads: one of the roads connects $s$ and the west end of the bridge, and the other one connects $t$ and the east end of the bridge. Note that each road doesn't have to be a straight line, but the intersection length with the river must be zero.
In order to cut building costs, the mayor intends to build a highway satisfying the following conditions:
Since bridge will cost more than roads, at first the length of a bridge connecting the east part and the west part must be as short as possible.
Under the above condition, the sum of the length of two roads is minimum.
Your task is to write a program computing the total length of a highway satisfying the above conditions.
Input
The input consists of a single test case. The test case is formatted as follows.
$sx$ $sy$ $tx$ $ty$
$N$
$wx_1$ $wy_1$
...
$wx_N$ $wy_N$
$M$
$ex_1$ $ey_1$
...
$ex_M$ $ey_M$
At first, we refer to a point on the city by a coordinate ($x, y$): the distance from the west side is $x$ and the distance from the north side is $y$.
The first line contains four integers $sx$, $sy$, $tx$, and $ty$ ($0 \leq sx, sy, tx, ty \leq 1,000$): points $s$ and $t$ are located at ($sx, sy$) and ($tx, ty$) respectively. The next line contains an integer $N$ ($2 \leq N \leq 20$), where $N$ is the number of points composing the west riverside. Each of the following $N$ lines contains two integers $wx_i$ and $wy_i$ ($0 \leq wx_i, wy_i \leq 1,000$): the coordinate of the $i$-th point of the west riverside is ($wx_i, wy_i$). The west riverside is a polygonal line obtained by connecting the segments between ($wx_i, wy_i$) and ($wx_{i+1}, wy_{i+1}$) for all $1 \leq i \leq N -1$. The next line contains an integer $M$ ($2 \leq M \leq 20$), where $M$ is the number of points composing the east riverside. Each of the following $M$ lines contains two integers $ex_i$ and $ey_i$ ($0 \leq ex_i, ey_i \leq 1,000$): the coordinate of the $i$-th point of the east riverside is ($ex_i, ey_i$). The east riverside is a polygonal line obtained by connecting the segments between ($ex_i, ey_i$) and ($ex_{i+1}, ey_{i+1}$) for all $1 \leq i \leq M - 1$.
You can assume that test cases are under the following conditions.
$wy_1$ and $ey_1$ must be 0, and $wy_N$ and $ey_M$ must be 1,000.
Each polygonal line has no self-intersection.
Two polygonal lines representing the west and the east riverside have no cross point.
A point $s$ must be on the west part of the city. More precisely, $s$ must be on the region surrounded by the square side of the city and the polygonal line of the west riverside and not containing the east riverside points.
A point $t$ must 
...(truncated)

Submitted solutions:

code_snippet: // AOJ #2735 Shortest Bridge
// 2025.3.25

#include <bits/stdc++.h>
using namespace std;
using ld = long double;

#define gc() getchar_unlocked()

int Cin() {
	int n = 0; int c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

const ld EPS = 1e-13;
const ld INF = 1e+10;
const ld PI = acosl(-1.0L);

int sgn(ld r) { return (r < -EPS) ? -1 : (r > EPS ? 1 : 0); }
ld ldAbs(ld a) { return max(a, -a); }

struct Pt {
    ld x, y;
    Pt() {}
    Pt(ld xx, ld yy) : x(xx), y(yy) {}
    Pt operator+(const Pt &a) const { return Pt(x + a.x, y + a.y); }
    Pt operator-(const Pt &a) const { return Pt(x - a.x, y - a.y); }
    Pt operator*(const Pt &a) const { return Pt(x * a.x - y * a.y, x * a.y + y * a.x); }
    Pt operator-() const { return Pt(-x, -y); }
    Pt operator*(const ld &k) const { return Pt(x * k, y * k); }
    Pt operator/(const ld &k) const { return Pt(x / k, y / k); }
    ld norm() const { return sqrt(x * x + y * y); }
    ld arg() const { return atan2(y, x); }
    ld dot(const Pt &a) const { return x * a.x + y * a.y; }
    ld det(const Pt &a) const { return x * a.y - y * a.x; }
    bool operator==(const Pt &a) const { return ((*this) - a).norm() < EPS; }
};

ld tri(const Pt &a, const Pt &b, const Pt &c) { return (b - a).det(c - a); }
int iSP(Pt a, Pt b, Pt c) {
    int s = sgn((b - a).det(c - a));
    if (s) return s;
    if (sgn((b - a).dot(c - a)) < 0) return -2;
    if (sgn((a - b).dot(c - b)) < 0) return 2;
    return 0;
}
int iLL(Pt a, Pt b, Pt c, Pt d) {
    if (sgn((b - a).det(d - c)) != 0) return 1;
    if (sgn((b - a).det(c - a)) != 0) return 0;
    return -1;
}
Pt pLL(Pt a, Pt b, Pt c, Pt d) {
    Pt v = b - a, w = d - c;
    return a + v * ((c - a).det(w) / v.det(w));
}
Pt hLP(Pt a, Pt b, Pt c) { return pLL(a, b, c, c + (b - a) * Pt(0, 1)); }
bool iSS(Pt a, Pt b, Pt c, Pt d) {
    return (iSP(a, b, c) * iSP(a, b, d) <= 0 &&
            iSP(c, d, a) * iSP(c, d, b) <= 0);
}
ld dLP(Pt a, Pt b, Pt c) { return ldAbs(tri(a, b, c)) / (b - a).norm(); }
ld dLL(Pt a, Pt b, Pt c, Pt d) { return iLL(a, b, c, d) ? 0 : dLP(a, b, c); }
ld dSP(Pt a, Pt b, Pt c) {
    if (sgn((b - a).dot(c - a)) <= 0) return (c - a).norm();
    if (sgn((a - b).dot(c - b)) <= 0) return (c - b).norm();
    return ldAbs(tri(a, b, c)) / (b - a).norm();
}
ld dSS(Pt a, Pt b, Pt c, Pt d) {
    if (iSS(a, b, c, d)) return 0;
    return min({ dSP(a, b, c), dSP(a, b, d), dSP(c, d, a), dSP(c, d, b) });
}
int sAP(Pt a, Pt b, Pt c) { return sgn(a.det(c)) - sgn(b.det(c)) - sgn(a.det(b)); }
int s_a[50], s_b[50], s_ab[50];
bool iGSstrict(int n, Pt p[], Pt a, Pt b) {
    p[n] = p[0];
    p[n+1] = p[1];
    for (int i = 0; i <= n; i++) {
        s_a[i] = sgn(tri(p[i], p[i+1], a));
        s_b[i] = sgn(tri(p[i], p[i+1], b));
        s_ab[i] = sgn(tri(a, b, p[i]));
    }
    for (int i = 0; i < n; i++) {
        if (s_a[i] * s_b[i] < 0 && s_ab[i] * s_ab[i+1] < 0) return true;
    }
    for (int i = 0; i < n; i++) {
        if (s_a[i] == 0 && s_b[i] > 0 && sgn((a - p[i]).dot(a - p[i+1])) < 0) return true;
        if (s_b[i] == 0 && s_a[i] > 0 && sgn((b - p[i]).dot(b - p[i+1])) < 0) return true;
    }
    for (int i = 0; i < n; i++) {
        if (s_ab[i+1] == 0 && sgn((p[i+1] - a).dot(p[i+1] - b)) <= 0) {
            if (!(p[i+1] == a) && sAP(p[i+2] - p[i+1], p[i] - p[i+1], a - p[i+1]) > 0)
                return true;
            if (!(p[i+1] == b) && sAP(p[i+2] - p[i+1], p[i] - p[i+1], b - p[i+1]) > 0)
                return true;
        }
    }
    return false;
}

int wn;
Pt wa[50];
Pt W[50], E[50];
int xs, es;
ld distArr[1100];
int vis[1100];
Pt varr[1100];
ld calc(Pt s, Pt t, int side) {
    for (int i = 0; i < 100; i++) {
        vis[i] = 0;
        distArr[i] = 999999999.9L;
    }
    int N = (side == 0) ? xs + 2 : es + 2;
    if (side == 0) {
        for (int i = 0; i < xs; i++) varr[i] = W[i];
        varr[xs]   = s;
        varr[xs+1] = t;
    } else {
        for (int i = 0; i < es; i++) varr[i] = E[i];
        varr[es]   = s;
        varr[es+1] = t;
    }
    distArr[N-2] = 0;
    for (int i = 0; i < N; i++) {
        ld tmp = 9999999999.9L;
        int at = 0;
        for (int j = 0; j < N; j++) {
            if (vis[j]) continue;
            if (distArr[j] < tmp) {
                tmp = distArr[j];
                at = j;
            }
        }
        vis[at] = 1;
        for (int j = 0; j < N; j++) {
            if (vis[j]) continue;
            ld d = (varr[j] - varr[at]).norm();
            if (distArr[j] < distArr[at] + d) continue;
            if (d < EPS) {
                distArr[j] = distArr[at];
                continue;
            }
            if (iGSstrict(wn, wa, varr[j], varr[at])) continue;
            distArr[j] = distArr[at] + d;
        }
    }
    return distArr[N-1];
}

int main(){
    ld sx = Cin(), sy = Cin(), tx = Cin(), ty = Cin();

    Pt s(sx, sy), t(tx, ty);
    int a = Cin();
    for (int i = 0; i < a; i++){
        ld x = Cin(), y = Cin();
        W[i] = Pt(x, y);
    }
    int b = Cin();
    for (int i = 0; i < b; i++){
        ld x = Cin(), y = Cin();
        E[i] = Pt(x, y);
    }
    xs = a; es = b;
    ld r1 = 999999999.0L;
    vector<pair<Pt, Pt>> bestPairs;
    vector<pair<pair<Pt, Pt>, pair<Pt, Pt>>> bli;
    for (int i = 0; i < a - 1; i++) {
        for (int j = 0; j < b - 1; j++) {
            ld d = dSS(W[i], W[i+1], E[j], E[j+1]);
            if (d < r1 - EPS) r1 = d;
        }
    }
    for (int i = 0; i < a - 1; i++) {
        for (int j = 0; j < b - 1; j++) {
            ld d = dSS(W[i], W[i+1], E[j], E[j+1]);
            if (d > r1 + EPS) continue;
            if (iLL(W[i], W[i+1], E[j], E[j+1]) == 1 || dLL(W[i], W[i+1], E[j], E[j+1]) < r1 - EPS) {
                if ((W[i] - E[j]).norm() < r1 + EPS)
                    bestPairs.push_back(make_pair(W[i], E[j]));
                if ((W[i] - E[j+1]).norm() < r1 + EPS)
                    bestPairs.push_back(make_pair(W[i], E[j+1]));
                if ((W[i+1] - E[j]).norm() < r1 + EPS)
                    bestPairs.push_back(make_pair(W[i+1], E[j]));
                if ((W[i+1] - E[j+1]).norm() < r1 + EPS)
                    bestPairs.push_back(make_pair(W[i+1], E[j+1]));
                Pt hp = hLP(E[j], E[j+1], W[i]);
                if ((W[i] - hp).norm() < r1 + EPS && iSP(E[j], hp, E[j+1]) == 2)
                    bestPairs.push_back(make_pair(W[i], hp));
                hp = hLP(E[j], E[j+1], W[i+1]);
                if ((W[i+1] - hp).norm() < r1 + EPS && iSP(E[j], hp, E[j+1]) == 2)
                    bestPairs.push_back(make_pair(W[i+1], hp));
                hp = hLP(W[i], W[i+1], E[j]);
                if ((E[j] - hp).norm() < r1 + EPS && iSP(W[i], hp, W[i+1]) == 2)
                    bestPairs.push_back(make_pair(hp, E[j]));
                hp = hLP(W[i], W[i+1], E[j+1]);
                if ((E[j+1] - hp).norm() < r1 + EPS && iSP(W[i], hp, W[i+1]) == 2)
                    bestPairs.push_back(make_pair(hp, E[j+1]));
            } else if (iLL(W[i], W[i+1], E[j], E[j+1]) == 0) {
                vector<Pt> tmp;
                tmp.push_back(hLP(W[i], W[i+1], E[j]));
                tmp.push_back(hLP(W[i], W[i+1], E[j+1]));
                tmp.push_back(W[i]);
                tmp.push_back(W[i+1]);
                for (int k = 0; k < 4; k++) {
                    for (int l = 0; l < 3; l++) {
                        if (tmp[l].x * 11451 + tmp[l].y * 810 > tmp[l+1].x * 11451 + tmp[l+1].y * 810)
                            swap(tmp[l], tmp[l+1]);
                    }
                }
                bli.push_back(make_pair(make_pair(tmp[1], tmp[2]),
                            make_pair(hLP(E[j], E[j+1], tmp[1]), hLP(E[j], E[j+1], tmp[2]))));
            }
        }
    }

    wn = 0;
    for (int i = 0; i < b; i++) wa[wn++] = E[i];
    wa[wn++] = Pt(500, 100000000);
    for (int i = a - 1; i >= 0; i--) wa[wn++] = W[i];
    wa[wn++] = Pt(500, -100000000);

    ld r2 = 999999999.0L;
    for (int i = 0; i < (int)bestPairs.size(); i++) {
        ld tmp = calc(s, bestPairs[i].first, 0) + calc(t, bestPairs[i].second, 1);
        r2 = min(r2, tmp);
    }
    for (int i = 0; i < (int)bli.size(); i++) {
        ld L = 0, R = 1;
        for (int j = 0; j < 100; j++) {
            ld m1 = (L * 2 + R) / 3;
            ld m2 = (L + R * 2) / 3;
            ld t1 = calc(s, bli[i].first.first * m1 + bli[i].first.second * (1.0 - m1), 0)
                             + calc(t, bli[i].second.first * m1 + bli[i].second.second * (1.0 - m1), 1);
            ld t2 = calc(s, bli[i].first.first * m2 + bli[i].first.second * (1.0 - m2), 0)
                             + calc(t, bli[i].second.first * m2 + bli[i].second.second * (1.0 - m2), 1);
            if (t1 > t2) L = m1;
            else R = m2;
            r2 = min(r2, min(t1, t2));
        }
    }
    printf("%.12Lf %.12Lf\n", r1, r1 + r2);
    return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 3612
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
// head

typedef long double db;
const db EPS = 1e-13;

inline int sign(db a) { return a < -EPS ? -1 : a > EPS; }

inline int cmp(db a, db b){ return sign(a-b); }

struct P {
	db x, y;
	P() {}
	P(db _x, db _y) : x(_x), y(_y) {}
	P operator+(P p) { return {x + p.x, y + p.y}; }
	P operator-(P p) { return {x - p.x, y - p.y}; }
	P operator*(db d) { return {x * d, y * d}; }
	P operator/(db d) { return {x / d, y / d}; }
 
	bool operator<(P p) const { 
		int c = cmp(x, p.x);
		if (c) return c == -1;
		return cmp(y, p.y) == -1;
	}
 
	bool operator==(P o) const{
		return cmp(x,o.x) == 0 && cmp(y,o.y) == 0;
	}
 
	db dot(P p) { return x * p.x + y * p.y; }
	db det(P p) { return x * p.y - y * p.x; }
	 
	db distTo(P p) { return (*this-p).abs(); }
	db alpha() { return atan2(y, x); }
	void read() { cin>>x>>y; }
	void write() {cout<<"("<<x<<","<<y<<")"<<endl;}
	db abs() { return sqrt(abs2());}
	db abs2() { return x * x + y * y; }
	P rot90() { return P(-y,x);}
	P unit() { return *this/abs(); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	P rot(db an){ return {x*cos(an)-y*sin(an),x*sin(an) + y*cos(an)}; }
};
 
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))
  
bool chkLL(P p1, P p2, P q1, P q2) {
	db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return sign(a1+a2) != 0;
}
 
P isLL(P p1, P p2, P q1, P q2) {
	db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return (p1 * a2 + p2 * a1) / (a1 + a2);
}
  
  
bool intersect(db l1,db r1,db l2,db r2){
	if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2); 
	return !( cmp(r1,l2) == -1 || cmp(r2,l1) == -1 );
}
  
bool isSS(P p1, P p2, P q1, P q2){
	return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) && 
	crossOp(p1,p2,q1) * crossOp(p1,p2,q2) <= 0 && crossOp(q1,q2,p1)
			* crossOp(q1,q2,p2) <= 0;
}
  
bool isSS_strict(P p1, P p2, P q1, P q2){
	return crossOp(p1,p2,q1) * crossOp(p1,p2,q2) < 0 && crossOp(q1,q2,p1)
			* crossOp(q1,q2,p2) < 0;
}
  
bool isMiddle(db a, db m, db b) {
	return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}
  
bool isMiddle(P a, P m, P b) {
	return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}
  
bool onSeg(P p1, P p2, P q){
	return crossOp(p1,p2,q) == 0 && isMiddle(p1, q, p2);
}
 
bool onSeg_strict(P p1, P p2, P q){
	return crossOp(p1,p2,q) == 0 && sign((q-p1).dot(p1-p2)) * sign((q-p2).dot(p1-p2)) < 0;
}
  
P proj(P p1, P p2, P q) {
	P dir = p2 - p1;
	return p1 + dir * (dir.dot(q - p1) / dir.abs2());
}
  
P reflect(P p1, P p2, P q){
	return proj(p1,p2,q) * 2 - q;
}
  
db nearest(P p1,P p2,P q){
	P h = proj(p1,p2,q);
	if(isMiddle(p1,h,p2))
		return q.distTo(h);
	return min(p1.distTo(q),p2.distTo(q));
}
  
db disSS(P p1, P p2, P q1, P q2){
	if(isSS(p1,p2,q1,q2)) return 0;
	return min(min(nearest(p1,p2,q1),nearest(p1,p2,q2)), min(nearest(q1,q2,p1),nearest(q1,q2,p2)));
}

int contain(vector<P> ps, P p){ //2:inside,1:on_seg,0:outside
	int n = ps.size(), ret = 0; 
	rep(i,0,n){
		P u=ps[i],v=ps[(i+1)%n];
		if(onSeg(u,v,p)) return 1;
		if(cmp(u.y,v.y)<=0) swap(u,v);
		if(cmp(p.y,u.y) >0 || cmp(p.y,v.y) <= 0) continue;
		ret ^= crossOp(p,u,v) > 0;
	}
	return ret*2;
}

const int N=30;
P s,t;
vector<P> p,q;
db r1,r2,dis[N][N],diss[N];
int n,m,g[2][N][N],vis[N];

bool valid(vector<P> p,P s,P t) {
	int n=SZ(p);
	rep(i,0,n) if (isSS_strict(p[i],p[(i+1)%n],s,t)) return 0;
	vector<P> cand; cand.pb(s); cand.pb(t);
	rep(i,0,n) if (onSeg(s,t,p[i])&&(!onSeg(s,t,p[(i+n-1)%n])||!onSeg(s,t,p[(i+1)%n]))) cand.pb(p[i]);
	sort(all(cand));
	cand.erase(unique(all(cand)),cand.end());
	rep(i,0,SZ(cand)-1) {
		P md=(cand[i]+cand[i+1])*0.5;
		if (contain(p,md)==0) return 0;
	}
	return 1;
}
db gao(vector<P> p,int d,P s,P t) {
	vector<P> q; q=p; q.pb(s); q.pb(t);
	int n=SZ(p);
	rep(i,0,n+2) rep(j,0,n+2) dis[i][j]=(i==j)?0:1e10;
	rep(i,0,n+2) rep(j,i+1,n+2) {
		if (i<n&&j<n) {
			if (g[d][i][j]) dis[i][j]=dis[j][i]=q[i].distTo(q[j]);
		} else if (valid(p,q[i],q[j])) dis[i][j]=dis[j][i]=q[i].distTo(q[j]);
	}
	n+=2;
	rep(i,0,n) diss[i]=1e30,vis[i]=0; diss[n-2]=0;
	rep(i,0,n) {
		int minp=-1; db minv=1e30;
		rep(j,0,n) if (diss[j]<minv&&!vis[j]) minv=diss[j],minp=j;
		vis[minp]=1;
		rep(j,0,n) diss[j]=min(diss[j],diss[minp]+dis[minp][j]);
	}
	return diss[n-1];
}

int main() {
	s.read(); t.read();
	scanf("%d",&n); n+=2;
	p.resize(n); p[0]=P(0,0); p[n-1]=P(0,1000);
	rep(i,1,n-1)  p[i].read();
	scanf("%d",&m); m+=2;
	q.resize(m); q[0]=P(1000,0); q[m-1]=P(1000,1000);
	rep(i,1,m-1) q[i].read();
	rep(i,0,n) rep(j,i,n) g[0][i][j]=g[0][j][i]=valid(p,p[i],p[j]);
	rep(i,0,m) rep(j,i,m) g[1][i][j]=g[1][j][i]=valid(q,q[i],q[j]);
	db r1=1e30,r2=1e30;
	rep(i,1,n-2) rep(j,1,m-2) r1=min(r1,disSS(p[i],p[i+1],q[j],q[j+1]));
	rep(i,1,n-1) rep(j,1,m-1) {
		db d1=p[i].distTo(q[j]);
		if (cmp(d1,r1)==0) {
			r2=min(r2,gao(p,0,s,p[i])+gao(q,1,t,q[j]));
		}
		if (j<m-2) {
			d1=nearest(q[j],q[j+1],p[i]);
			if (cmp(d1,r1)==0) {
				P r=proj(q[j],q[j+1],p[i]);
				if (isMiddle(q[j],r,q[j+1])) r2=min(r2,gao(p,0,s,p[i])+gao(q,1,t,r));
			}
		}
		if (i<n-2) {
			d1=nearest(p[i],p[i+1],q[j]);
			if (cmp(d1,r1)==0) {
				P r=proj(p[i],p[i+1],q[j]);
				if (isMiddle(p[i],r,p[i+1])) r2=min(r2,gao(p,0,s,r)+gao(q,1,t,q[j]));
			}
		}
	}
	rep(i,1,n-2) rep(j,1,m-2) {
		db d1=disSS(p[i],p[i+1],q[j],q[j+1]);
		if (cmp(d1,r1)>0) continue;
		if (sign((p[i+1]-p[i]).det(q[j+1]-q[j]))!=0) continue;
		P pl=p[i],pr=p[i+1];
		if (!isMiddle(q[j],proj(q[j],q[j+1],pl),q[j+1])) pl=proj(p[i],p[i+1],q[j]);
		if (!isMiddle(q[j],proj(q[j],q[j+1],pr),q[j+1])) pr=proj(p[i],p[i+1],q[j+1]);
		if (!isMiddle(p[i],pl,p[i+1])||!isMiddle(p[i],pr,p[i+1])) continue;
		rep(it,0,40) {
			P fl=(pl+pl+pr)/3,fr=(pl+pr+pr)/3;
			db vl=gao(p,0,s,fl)+gao(q,1,proj(q[j],q[j+1],fl),t);
			db vr=gao(p,0,s,fr)+gao(q,1,proj(q[j],q[j+1],fr),t);
			r2=min(r2,min(vl,vr));
			if (vl>vr) pl=fl; else pr=fr;
		}
	}
	printf("%.10f %.10f\n",(double)r1,(double)(r1+r2));
}
accuracy: 1
time_ms: 750
memory_kb: 3344
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
// head

typedef long double db;
const db EPS = 1e-13;

inline int sign(db a) { return a < -EPS ? -1 : a > EPS; }

inline int cmp(db a, db b){ return sign(a-b); }

struct P {
	db x, y;
	P() {}
	P(db _x, db _y) : x(_x), y(_y) {}
	P operator+(P p) { return {x + p.x, y + p.y}; }
	P operator-(P p) { return {x - p.x, y - p.y}; }
	P operator*(db d) { return {x * d, y * d}; }
	P operator/(db d) { return {x / d, y / d}; }
 
	bool operator<(P p) const { 
		int c = cmp(x, p.x);
		if (c) return c == -1;
		return cmp(y, p.y) == -1;
	}
 
	bool operator==(P o) const{
		return cmp(x,o.x) == 0 && cmp(y,o.y) == 0;
	}
 
	db dot(P p) { return x * p.x + y * p.y; }
	db det(P p) { return x * p.y - y * p.x; }
	 
	db distTo(P p) { return (*this-p).abs(); }
	db alpha() { return atan2(y, x); }
	void read() { cin>>x>>y; }
	void write() {cout<<"("<<x<<","<<y<<")"<<endl;}
	db abs() { return sqrt(abs2());}
	db abs2() { return x * x + y * y; }
	P rot90() { return P(-y,x);}
	P unit() { return *this/abs(); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	P rot(db an){ return {x*cos(an)-y*sin(an),x*sin(an) + y*cos(an)}; }
};
 
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))
  
bool chkLL(P p1, P p2, P q1, P q2) {
	db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return sign(a1+a2) != 0;
}
 
P isLL(P p1, P p2, P q1, P q2) {
	db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return (p1 * a2 + p2 * a1) / (a1 + a2);
}
  
  
bool intersect(db l1,db r1,db l2,db r2){
	if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2); 
	return !( cmp(r1,l2) == -1 || cmp(r2,l1) == -1 );
}
  
bool isSS(P p1, P p2, P q1, P q2){
	return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) && 
	crossOp(p1,p2,q1) * crossOp(p1,p2,q2) <= 0 && crossOp(q1,q2,p1)
			* crossOp(q1,q2,p2) <= 0;
}
  
bool isSS_strict(P p1, P p2, P q1, P q2){
	return crossOp(p1,p2,q1) * crossOp(p1,p2,q2) < 0 && crossOp(q1,q2,p1)
			* crossOp(q1,q2,p2) < 0;
}
  
bool isMiddle(db a, db m, db b) {
	return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}
  
bool isMiddle(P a, P m, P b) {
	return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}
  
bool onSeg(P p1, P p2, P q){
	return crossOp(p1,p2,q) == 0 && isMiddle(p1, q, p2);
}
 
bool onSeg_strict(P p1, P p2, P q){
	return crossOp(p1,p2,q) == 0 && sign((q-p1).dot(p1-p2)) * sign((q-p2).dot(p1-p2)) < 0;
}
  
P proj(P p1, P p2, P q) {
	P dir = p2 - p1;
	return p1 + dir * (dir.dot(q - p1) / dir.abs2());
}
  
P reflect(P p1, P p2, P q){
	return proj(p1,p2,q) * 2 - q;
}
  
db nearest(P p1,P p2,P q){
	P h = proj(p1,p2,q);
	if(isMiddle(p1,h,p2))
		return q.distTo(h);
	return min(p1.distTo(q),p2.distTo(q));
}
  
db disSS(P p1, P p2, P q1, P q2){
	if(isSS(p1,p2,q1,q2)) return 0;
	return min(min(nearest(p1,p2,q1),nearest(p1,p2,q2)), min(nearest(q1,q2,p1),nearest(q1,q2,p2)));
}

int contain(vector<P> ps, P p){ //2:inside,1:on_seg,0:outside
	int n = ps.size(), ret = 0; 
	rep(i,0,n){
		P u=ps[i],v=ps[(i+1)%n];
		if(onSeg(u,v,p)) return 1;
		if(cmp(u.y,v.y)<=0) swap(u,v);
		if(cmp(p.y,u.y) >0 || cmp(p.y,v.y) <= 0) continue;
		ret ^= crossOp(p,u,v) > 0;
	}
	return ret*2;
}

const int N=30;
P s,t;
vector<P> p,q;
db r1,r2,dis[N][N],diss[N];
int n,m,g[2][N][N],vis[N];

bool valid(vector<P> p,P s,P t) {
	int n=SZ(p);
	rep(i,0,n) if (isSS_strict(p[i],p[(i+1)%n],s,t)) return 0;
	vector<P> cand; cand.pb(s); cand.pb(t);
	rep(i,0,n) if (onSeg(s,t,p[i])) cand.pb(p[i]);
	sort(all(cand));
	cand.erase(unique(all(cand)),cand.end());
	rep(i,0,SZ(cand)-1) {
		P md=(cand[i]+cand[i+1])*0.5;
		if (contain(p,md)==0) return 0;
	}
	return 1;
}
db gao(vector<P> p,int d,P s,P t) {
	vector<P> q; q=p; q.pb(s); q.pb(t);
	int n=SZ(p);
	rep(i,0,n+2) rep(j,0,n+2) dis[i][j]=(i==j)?0:1e10;
	rep(i,0,n+2) rep(j,i+1,n+2) {
		if (i<n&&j<n) {
			if (g[d][i][j]) dis[i][j]=dis[j][i]=q[i].distTo(q[j]);
		} else if (valid(p,q[i],q[j])) dis[i][j]=dis[j][i]=q[i].distTo(q[j]);
	}
	n+=2;
	rep(i,0,n) diss[i]=1e30,vis[i]=0; diss[n-2]=0;
	rep(i,0,n) {
		int minp=-1; db minv=1e30;
		rep(j,0,n) if (diss[j]<minv&&!vis[j]) minv=diss[j],minp=j;
		vis[minp]=1;
		rep(j,0,n) diss[j]=min(diss[j],diss[minp]+dis[minp][j]);
	}
	return diss[n-1];
}

int main() {
	s.read(); t.read();
	scanf("%d",&n); n+=2;
	p.resize(n); p[0]=P(0,0); p[n-1]=P(0,1000);
	rep(i,1,n-1)  p[i].read();
	scanf("%d",&m); m+=2;
	q.resize(m); q[0]=P(1000,0); q[m-1]=P(1000,1000);
	rep(i,1,m-1) q[i].read();
	rep(i,0,n) rep(j,i,n) g[0][i][j]=g[0][j][i]=valid(p,p[i],p[j]);
	rep(i,0,m) rep(j,i,m) g[1][i][j]=g[1][j][i]=valid(q,q[i],q[j]);
	db r1=1e30,r2=1e30;
	rep(i,1,n-2) rep(j,1,m-2) r1=min(r1,disSS(p[i],p[i+1],q[j],q[j+1]));
	rep(i,1,n-1) rep(j,1,m-1) {
		db d1=p[i].distTo(q[j]);
		if (cmp(d1,r1)==0) {
			r2=min(r2,gao(p,0,s,p[i])+gao(q,1,t,q[j]));
		}
		if (j<m-2) {
			d1=nearest(q[j],q[j+1],p[i]);
			if (cmp(d1,r1)==0) {
				P r=proj(q[j],q[j+1],p[i]);
				if (isMiddle(q[j],r,q[j+1])) r2=min(r2,gao(p,0,s,p[i])+gao(q,1,t,r));
			}
		}
		if (i<n-2) {
			d1=nearest(p[i],p[i+1],q[j]);
			if (cmp(d1,r1)==0) {
				P r=proj(p[i],p[i+1],q[j]);
				if (isMiddle(p[i],r,p[i+1])) r2=min(r2,gao(p,0,s,r)+gao(q,1,t,q[j]));
			}
		}
	}
	rep(i,1,n-2) rep(j,1,m-2) {
		db d1=disSS(p[i],p[i+1],q[j],q[j+1]);
		if (cmp(d1,r1)>0) continue;
		if (sign((p[i+1]-p[i]).det(q[j+1]-q[j]))!=0) continue;
		P pl=p[i],pr=p[i+1];
		if (!isMiddle(q[j],proj(q[j],q[j+1],pl),q[j+1])) pl=proj(p[i],p[i+1],q[j]);
		if (!isMiddle(q[j],proj(q[j],q[j+1],pr),q[j+1])) pr=proj(p[i],p[i+1],q[j+1]);
		if (!isMiddle(p[i],pl,p[i+1])||!isMiddle(p[i],pr,p[i+1])) continue;
		rep(it,0,40) {
			P fl=(pl+pl+pr)/3,fr=(pl+pr+pr)/3;
			db vl=gao(p,0,s,fl)+gao(q,1,proj(q[j],q[j+1],fl),t);
			db vr=gao(p,0,s,fr)+gao(q,1,proj(q[j],q[j+1],fr),t);
			r2=min(r2,min(vl,vr));
			if (vl>vr) pl=fl; else pr=fr;
		}
	}
	printf("%.10f %.10f\n",(double)r1,(double)(r1+r2));
}
accuracy: 1
time_ms: 1130
memory_kb: 3340
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
// head

typedef long double db;
const db EPS = 1e-13;

inline int sign(db a) { return a < -EPS ? -1 : a > EPS; }

inline int cmp(db a, db b){ return sign(a-b); }

struct P {
	db x, y;
	P() {}
	P(db _x, db _y) : x(_x), y(_y) {}
	P operator+(P p) { return {x + p.x, y + p.y}; }
	P operator-(P p) { return {x - p.x, y - p.y}; }
	P operator*(db d) { return {x * d, y * d}; }
	P operator/(db d) { return {x / d, y / d}; }
 
	bool operator<(P p) const { 
		int c = cmp(x, p.x);
		if (c) return c == -1;
		return cmp(y, p.y) == -1;
	}
 
	bool operator==(P o) const{
		return cmp(x,o.x) == 0 && cmp(y,o.y) == 0;
	}
 
	db dot(P p) { return x * p.x + y * p.y; }
	db det(P p) { return x * p.y - y * p.x; }
	 
	db distTo(P p) { return (*this-p).abs(); }
	db alpha() { return atan2(y, x); }
	void read() { cin>>x>>y; }
	void write() {cout<<"("<<x<<","<<y<<")"<<endl;}
	db abs() { return sqrt(abs2());}
	db abs2() { return x * x + y * y; }
	P rot90() { return P(-y,x);}
	P unit() { return *this/abs(); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	P rot(db an){ return {x*cos(an)-y*sin(an),x*sin(an) + y*cos(an)}; }
};
 
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))
  
bool chkLL(P p1, P p2, P q1, P q2) {
	db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return sign(a1+a2) != 0;
}
 
P isLL(P p1, P p2, P q1, P q2) {
	db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return (p1 * a2 + p2 * a1) / (a1 + a2);
}
  
  
bool intersect(db l1,db r1,db l2,db r2){
	if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2); 
	return !( cmp(r1,l2) == -1 || cmp(r2,l1) == -1 );
}
  
bool isSS(P p1, P p2, P q1, P q2){
	return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) && 
	crossOp(p1,p2,q1) * crossOp(p1,p2,q2) <= 0 && crossOp(q1,q2,p1)
			* crossOp(q1,q2,p2) <= 0;
}
  
bool isSS_strict(P p1, P p2, P q1, P q2){
	return crossOp(p1,p2,q1) * crossOp(p1,p2,q2) < 0 && crossOp(q1,q2,p1)
			* crossOp(q1,q2,p2) < 0;
}
  
bool isMiddle(db a, db m, db b) {
	return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}
  
bool isMiddle(P a, P m, P b) {
	return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}
  
bool onSeg(P p1, P p2, P q){
	return crossOp(p1,p2,q) == 0 && isMiddle(p1, q, p2);
}
 
bool onSeg_strict(P p1, P p2, P q){
	return crossOp(p1,p2,q) == 0 && sign((q-p1).dot(p1-p2)) * sign((q-p2).dot(p1-p2)) < 0;
}
  
P proj(P p1, P p2, P q) {
	P dir = p2 - p1;
	return p1 + dir * (dir.dot(q - p1) / dir.abs2());
}
  
P reflect(P p1, P p2, P q){
	return proj(p1,p2,q) * 2 - q;
}
  
db nearest(P p1,P p2,P q){
	P h = proj(p1,p2,q);
	if(isMiddle(p1,h,p2))
		return q.distTo(h);
	return min(p1.distTo(q),p2.distTo(q));
}
  
db disSS(P p1, P p2, P q1, P q2){
	if(isSS(p1,p2,q1,q2)) return 0;
	return min(min(nearest(p1,p2,q1),nearest(p1,p2,q2)), min(nearest(q1,q2,p1),nearest(q1,q2,p2)));
}

int contain(vector<P> ps, P p){ //2:inside,1:on_seg,0:outside
	int n = ps.size(), ret = 0; 
	rep(i,0,n){
		P u=ps[i],v=ps[(i+1)%n];
		if(onSeg(u,v,p)) return 1;
		if(cmp(u.y,v.y)<=0) swap(u,v);
		if(cmp(p.y,u.y) >0 || cmp(p.y,v.y) <= 0) continue;
		ret ^= crossOp(p,u,v) > 0;
	}
	return ret*2;
}

const int N=30;
P s,t;
vector<P> p,q;
db r1,r2,dis[N][N];
int n,m,g[2][N][N];

bool valid(vector<P> p,P s,P t) {
	int n=SZ(p);
	rep(i,0,n) if (isSS_strict(p[i],p[(i+1)%n],s,t)) return 0;
	vector<P> cand; cand.pb(s); cand.pb(t);
	rep(i,0,n) if (onSeg(s,t,p[i])) cand.pb(p[i]);
	sort(all(cand));
	cand.erase(unique(all(cand)),cand.end());
	rep(i,0,SZ(cand)-1) {
		P md=(cand[i]+cand[i+1])*0.5;
		if (contain(p,md)==0) return 0;
	}
	return 1;
}
db gao(vector<P> p,int d,P s,P t) {
	vector<P> q; q=p; q.pb(s); q.pb(t);
	int n=SZ(p);
	rep(i,0,n+2) rep(j,0,n+2) dis[i][j]=(i==j)?0:1e10;
	rep(i,0,n+2) rep(j,i+1,n+2) {
		if (i<n&&j<n) {
			if (g[d][i][j]) dis[i][j]=dis[j][i]=q[i].distTo(q[j]);
		} else if (valid(p,q[i],q[j])) dis[i][j]=dis[j][i]=q[i].distTo(q[j]);
	}
	rep(k,0,n+2) rep(i,0,n+2) rep(j,0,n+2) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
	return dis[n][n+1];
}

int main() {
	s.read(); t.read();
	scanf("%d",&n); n+=2;
	p.resize(n); p[0]=P(0,0); p[n-1]=P(0,1000);
	rep(i,1,n-1)  p[i].read();
	scanf("%d",&m); m+=2;
	q.resize(m); q[0]=P(1000,0); 	q[m-1]=P(1000,1000);
	rep(i,1,m-1) q[i].read();
	rep(i,0,n) rep(j,i,n) g[0][i][j]=g[0][j][i]=valid(p,p[i],p[j]);
	rep(i,0,m) rep(j,i,m) g[1][i][j]=g[1][j][i]=valid(q,q[i],q[j]);
	db r1=1e30,r2=1e30;
	rep(i,1,n-2) rep(j,1,m-2) r1=min(r1,disSS(p[i],p[i+1],q[j],q[j+1]));
	rep(i,1,n-1) rep(j,1,m-1) {
		db d1=p[i].distTo(q[j]);
		if (cmp(d1,r1)==0) {
			r2=min(r2,gao(p,0,s,p[i])+gao(q,1,t,q[j]));
		}
		if (j<m-2) {
			d1=nearest(q[j],q[j+1],p[i]);
			if (cmp(d1,r1)==0) {
				P r=proj(q[j],q[j+1],p[i]);
				if (isMiddle(q[j],r,q[j+1])) r2=min(r2,gao(p,0,s,p[i])+gao(q,1,t,r));
			}
		}
		if (i<n-2) {
			d1=nearest(p[i],p[i+1],q[j]);
			if (cmp(d1,r1)==0) {
				P r=proj(p[i],p[i+1],q[j]);
				if (isMiddle(p[i],r,p[i+1])) r2=min(r2,gao(p,0,s,r)+gao(q,1,t,q[j]));
			}
		}
	}
	rep(i,1,n-2) rep(j,1,m-2) {
		db d1=disSS(p[i],p[i+1],q[j],q[j+1]);
		if (cmp(d1,r1)>0) continue;
		if (sign((p[i+1]-p[i]).det(q[j+1]-q[j]))!=0) continue;
		P pl=p[i],pr=p[i+1];
		if (!isMiddle(q[j],proj(q[j],q[j+1],pl),q[j+1])) pl=proj(p[i],p[i+1],q[j]);
		if (!isMiddle(q[j],proj(q[j],q[j+1],pr),q[j+1])) pr=proj(p[i],p[i+1],q[j+1]);
		if (!isMiddle(p[i],pl,p[i+1])||!isMiddle(p[i],pr,p[i+1])) continue;
		rep(it,0,100) {
			P fl=(pl+pl+pr)/3,fr=(pl+pr+pr)/3;
			db vl=gao(p,0,s,fl)+gao(q,1,proj(q[j],q[j+1],fl),t);
			db vr=gao(p,0,s,fr)+gao(q,1,proj(q[j],q[j+1],fr),t);
			r2=min(r2,min(vl,vr));
			if (vl>vr) pl=fl; else pr=fr;
		}
	}
	printf("%.10f %.10f\n",(double)r1,(double)(r1+r2));
}
accuracy: 1
time_ms: 3690
memory_kb: 3344
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=(a);i<(n);i++)
#define per(i,a,n) for(int i=(n)-1;i>=(a);i--)
#define mp make_pair
#define pb push_back

typedef long double db;

template<class T> inline void cmin(T&x,T c){if(c<x)x=c;}
template<class T> inline void cmax(T&x,T c){if(c>x)x=c;}
 
const db EPS = 1e-8;
 
inline int sign(db a) {
    return a < -EPS ? -1 : a > EPS;
}
 
inline int cmp(db a, db b){
    return sign(a-b);
}
 
struct P {
    db x, y;
    P() {}
    P(db _x, db _y) : x(_x), y(_y) {}
    P operator+(P p) { return P(x + p.x, y + p.y); }
    P operator-(P p) { return P(x - p.x, y - p.y); }
    P operator*(db d) { return P(x * d, y * d); }
    P operator/(db d) { return P(x / d, y / d); }
    bool operator<(P p) const { 
        int c = cmp(x, p.x);
        if (c) return c == -1;
        return cmp(y, p.y) == -1;
    }
    db dot(P p) { return x * p.x + y * p.y; }
    db det(P p) { return x * p.y - y * p.x; }
    db distTo(P p) { return (*this-p).abs(); }
    db alpha() { return atan2(y, x); }
    void read() { cin>>x>>y; }
    db abs() { return sqrt(abs2());}
    db abs2() { return x * x + y * y; }
    P rot90() { return P(-y,x);}
    P unit() { return *this/abs(); }
};
 
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))

P isLL(P p1, P p2, P q1, P q2) {
    db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
    return (p1 * a2 + p2 * a1) / (a1 + a2);
}

bool crsLL(P p1, P p2, P q1, P q2){
    db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
    return sign(a1+a2) != 0;
}

bool isMiddle(db a, db m, db b) {
    return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}
  
bool isMiddle(P a, P m, P b) {
    return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}

bool onSeg(P p1, P p2, P q){
    return crossOp(p1,p2,q) == 0 && isMiddle(p1, q, p2);
}

P vs,vt;
int N,M;
vector<P> W,E;

int contain(vector<P> ps, P p){ //2:inside,1:on_seg,0:outside
    int n = ps.size(), ret = 0; 
    rep(i,0,n){
        P u=ps[i],v=ps[(i+1)%n];
        if(onSeg(u,v,p)) return 1;
        if(cmp(u.y,v.y)<=0) swap(u,v);
        if(cmp(p.y,u.y) >0 || cmp(p.y,v.y) <= 0) continue;
        ret ^= crossOp(p,u,v) > 0;
    }
    return ret*2;
}

bool check(vector<P> ps, P s, P t){
	vector<P> important;
	int n=ps.size();

	rep(i,0,n){
		P p1=ps[i],p2=ps[(i+1)%n];
		if(crsLL(p1,p2,s,t)){
			P q = isLL(p1,p2,s,t);
			if(isMiddle(s,q,t))
				important.pb(q);
		}
	}
	important.pb(s);
	important.pb(t);
	sort(important.begin(), important.end());

	rep(i,0,important.size() - 1){
		if((important[i] - important[i+1]).abs() > EPS){
			P p = (important[i] + important[i+1])/2;
			if(contain(ps,p) == 0) return 0;
		}
	}

	return 1;
}

db dijstra(vector<P> ps, P s, P t,int tp){

	static bool first[2] = {1,1};
	static bool can[2][30][30] = {};
	static db edge[2][30][30];

	vector<P> qs = ps;

	qs.pb(s);qs.pb(t);

	int n = qs.size();

	if(first[tp]){
		rep(i,0,n) rep(j,0,i){
			can[tp][i][j] = can[tp][j][i] = check(ps,qs[i],qs[j]);
			edge[tp][i][j] = edge[tp][j][i] = (qs[i] - qs[j]).abs();
		}
		first[tp] = 0;
	} else {
		rep(i,n-2,n) rep(j,0,i){
			can[tp][i][j] = can[tp][j][i] = check(ps,qs[i],qs[j]);
			edge[tp][i][j] = edge[tp][j][i] = (qs[i] - qs[j]).abs();
		}
	}

	db dist[30] = {};
	bool used[30] = {};
	rep(i,0,n) dist[i] = 1e100;

	dist[n-2] = 0;

	rep(i,0,n){
		int u = -1;
		rep(i,0,n) if(!used[i] && (u == -1 || dist[i] < dist[u])) u = i;
		used[u] = 1;
		rep(i,0,n) if(can[tp][u][i]){
			cmin(dist[i],dist[u] + edge[tp][u][i]);
		}
	}

	return dist[n-1];
} 


P proj(P p1, P p2, P q) {
    P dir = p2 - p1;
    return p1 + dir * (dir.dot(q - p1) / dir.abs2());
}

db nearest(P p1,P p2,P q){
    P h = proj(p1,p2,q);
    if(isMiddle(p1,h,p2))
        return q.distTo(h);
    return min(p1.distTo(q),p2.distTo(q));
}

P nearestP(P p1,P p2,P q){
    P h = proj(p1,p2,q);
    if(isMiddle(p1,h,p2))
        return h;
    if(p1.distTo(q) < p2.distTo(q))
    	return p1;
    else
    	return p2;
}

db bridge,total;

void update(db br,db tot){
	if(abs(br-bridge) <= 1e-14){
		cmin(total,tot);
		return;
	}
	if(br < bridge){
		bridge = br;
		total = tot;
	}
}

P getP(P st, P dir, db dt){
	return st + dir * (dt - st.dot(dir));
}

void solve(P w1,P w2,P e1,P e2){
	// w1 -- w2
	// e1 -- e2

	//four cases
	rep(i,0,2){
		P me = i?w2:w1;
		P p = nearestP(e1,e2,me);
		update(p.distTo(me), dijstra(W,vs,me,0) + dijstra(E,p,vt,1));
	}

	rep(i,0,2){
		P me = i?e2:e1;
		P p = nearestP(w1,w2,me);
		update(p.distTo(me), dijstra(W,vs,p,0) + dijstra(E,me,vt,1));
	}

	//a special case
	if(sign((w2-w1).det(e2-e1)) == 0){
		P dir = (e2-e1).unit();
		if(w2.dot(dir) < w1.dot(dir)) swap(w1,w2);

		db l = max(e1.dot(dir),w1.dot(dir));
		db r = min(e2.dot(dir),w2.dot(dir));

		if(cmp(l,r) >= 0) return;

		db ret = getP(w1,dir,l).distTo(getP(e1,dir,l));

		if(ret > bridge + 1e-14) return;

		auto calc = [w1,e1,dir](db x){
			P pW = getP(w1,dir,x);
			P pE = getP(e1,dir,x);
			return dijstra(W,vs,pW,0) + dijstra(E,pE,vt,1);
		};

		rep(it,0,60){
			db L = (l*2+r)/3, R = (l+2*r)/3;

			if(calc(L) < calc(R))
				r=R;
			else
				l=L;
		}

		update(ret, calc(l));
	}
}

int main(){
	vs.read();vt.read();
	cin>>N; W.resize(N); rep(i,0,N) W[i].read(); W.pb({0,1000}); W.pb({0,0});


	cin>>M; E.resize(M); rep(i,0,M) E[i].read(); E.pb({1000,1000}); E.pb({1000,0});

	bridge = 1e100; total = 1e100;

	rep(i,0,W.size()) rep(j,0,E.size()) solve(W[i],W[(i+1)%W.size()],E[j],E[(j+1)%E.size()]);

	printf("%0.10f %0.10f\n", (double)bridge, (double)(bridge + total));
}
accuracy: 1
time_ms: 590
memory_kb: 3296
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=(a);i<(n);i++)
#define per(i,a,n) for(int i=(n)-1;i>=(a);i--)
#define mp make_pair
#define pb push_back

typedef long double db;

template<class T> inline void cmin(T&x,T c){if(c<x)x=c;}
template<class T> inline void cmax(T&x,T c){if(c>x)x=c;}
 
const db EPS = 1e-8;
 
inline int sign(db a) {
    return a < -EPS ? -1 : a > EPS;
}
 
inline int cmp(db a, db b){
    return sign(a-b);
}
 
struct P {
    db x, y;
    P() {}
    P(db _x, db _y) : x(_x), y(_y) {}
    P operator+(P p) { return P(x + p.x, y + p.y); }
    P operator-(P p) { return P(x - p.x, y - p.y); }
    P operator*(db d) { return P(x * d, y * d); }
    P operator/(db d) { return P(x / d, y / d); }
    bool operator<(P p) const { 
        int c = cmp(x, p.x);
        if (c) return c == -1;
        return cmp(y, p.y) == -1;
    }
    db dot(P p) { return x * p.x + y * p.y; }
    db det(P p) { return x * p.y - y * p.x; }
    db distTo(P p) { return (*this-p).abs(); }
    db alpha() { return atan2(y, x); }
    void read() { cin>>x>>y; }
    db abs() { return sqrt(abs2());}
    db abs2() { return x * x + y * y; }
    P rot90() { return P(-y,x);}
    P unit() { return *this/abs(); }
};
 
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))

P isLL(P p1, P p2, P q1, P q2) {
    db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
    return (p1 * a2 + p2 * a1) / (a1 + a2);
}

bool crsLL(P p1, P p2, P q1, P q2){
    db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
    return sign(a1+a2) != 0;
}

bool isMiddle(db a, db m, db b) {
    return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}
  
bool isMiddle(P a, P m, P b) {
    return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}

bool onSeg(P p1, P p2, P q){
    return crossOp(p1,p2,q) == 0 && isMiddle(p1, q, p2);
}

P vs,vt;
int N,M;
vector<P> W,E;

int contain(vector<P> ps, P p){ //2:inside,1:on_seg,0:outside
    int n = ps.size(), ret = 0; 
    rep(i,0,n){
        P u=ps[i],v=ps[(i+1)%n];
        if(onSeg(u,v,p)) return 1;
        if(cmp(u.y,v.y)<=0) swap(u,v);
        if(cmp(p.y,u.y) >0 || cmp(p.y,v.y) <= 0) continue;
        ret ^= crossOp(p,u,v) > 0;
    }
    return ret*2;
}

bool check(vector<P> ps, P s, P t){
	vector<P> important;
	int n=ps.size();

	rep(i,0,n){
		P p1=ps[i],p2=ps[(i+1)%n];
		if(crsLL(p1,p2,s,t)){
			P q = isLL(p1,p2,s,t);
			if(isMiddle(s,q,t))
				important.pb(q);
		}
	}
	important.pb(s);
	important.pb(t);
	sort(important.begin(), important.end());

	rep(i,0,important.size() - 1){
		if((important[i] - important[i+1]).abs() > EPS){
			P p = (important[i] + important[i+1])/2;
			if(contain(ps,p) == 0) return 0;
		}
	}

	return 1;
}

db dijstra(vector<P> ps, P s, P t,int tp){

	static bool first[2] = {1,1};
	static bool can[2][30][30] = {};
	static db edge[2][30][30];

	vector<P> qs = ps;

	qs.pb(s);qs.pb(t);

	int n = qs.size();

	if(first[tp]){
		rep(i,0,n) rep(j,0,i){
			can[tp][i][j] = can[tp][j][i] = check(ps,qs[i],qs[j]);
			edge[tp][i][j] = edge[tp][j][i] = (qs[i] - qs[j]).abs();
		}
		first[tp] = 0;
	} else {
		rep(i,n-2,n) rep(j,0,i){
			can[tp][i][j] = can[tp][j][i] = check(ps,qs[i],qs[j]);
			edge[tp][i][j] = edge[tp][j][i] = (qs[i] - qs[j]).abs();
		}
	}

	db dist[30] = {};
	bool used[30] = {};
	rep(i,0,n) dist[i] = 1e100;

	dist[n-2] = 0;

	rep(i,0,n){
		int u = -1;
		rep(i,0,n) if(!used[i] && (u == -1 || dist[i] < dist[u])) u = i;
		used[u] = 1;
		rep(i,0,n) if(can[tp][u][i]){
			cmin(dist[i],dist[u] + edge[tp][u][i]);
		}
	}

	return dist[n-1];
} 


P proj(P p1, P p2, P q) {
    P dir = p2 - p1;
    return p1 + dir * (dir.dot(q - p1) / dir.abs2());
}

db nearest(P p1,P p2,P q){
    P h = proj(p1,p2,q);
    if(isMiddle(p1,h,p2))
        return q.distTo(h);
    return min(p1.distTo(q),p2.distTo(q));
}

P nearestP(P p1,P p2,P q){
    P h = proj(p1,p2,q);
    if(isMiddle(p1,h,p2))
        return h;
    if(p1.distTo(q) < p2.distTo(q))
    	return p1;
    else
    	return p2;
}

db bridge,total;

void update(db br,db tot){
	if(abs(br-bridge) <= 1e-14){
		cmin(total,tot);
		return;
	}
	if(br < bridge){
		bridge = br;
		total = tot;
	}
}

P getP(P st, P dir, db dt){
	return st + dir * (dt - st.dot(dir));
}

void solve(P w1,P w2,P e1,P e2){
	// w1 -- w2
	// e1 -- e2

	//four cases
	rep(i,0,2){
		P me = i?w2:w1;
		P p = nearestP(e1,e2,me);
		update(p.distTo(me), dijstra(W,vs,me,0) + dijstra(E,p,vt,1));
	}

	rep(i,0,2){
		P me = i?e2:e1;
		P p = nearestP(w1,w2,me);
		update(p.distTo(me), dijstra(W,vs,p,0) + dijstra(E,me,vt,1));
	}

	//a special case
	if(sign((w2-w1).det(e2-e1)) == 0){
		P dir = (e2-e1).unit();
		if(w2.dot(dir) < w1.dot(dir)) swap(w1,w2);

		db l = max(e1.dot(dir),w1.dot(dir));
		db r = min(e2.dot(dir),w2.dot(dir));

		if(cmp(l,r) >= 0) return;

		auto calc = [w1,e1,dir](db x){
			P pW = getP(w1,dir,x);
			P pE = getP(e1,dir,x);
			return dijstra(W,vs,pW,0) + dijstra(E,pE,vt,1);
		};

		rep(it,0,100){
			db L = (l*2+r)/3, R = (l+2*r)/3;

			if(calc(L) < calc(R))
				r=R;
			else
				l=L;
		}

		update(getP(w1,dir,l).distTo(getP(e1,dir,l)), calc(l));
	}
}

int main(){
	vs.read();vt.read();
	cin>>N; W.resize(N); rep(i,0,N) W[i].read(); W.pb({0,1000}); W.pb({0,0});


	cin>>M; E.resize(M); rep(i,0,M) E[i].read(); E.pb({1000,1000}); E.pb({1000,0});

	bridge = 1e100; total = 1e100;

	rep(i,0,W.size()) rep(j,0,E.size()) solve(W[i],W[(i+1)%W.size()],E[j],E[(j+1)%E.size()]);

	printf("%0.10f %0.10f\n", (double)bridge, (double)(bridge + total));
}
accuracy: 1
time_ms: 2080
memory_kb: 3296
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=(a);i<(n);i++)
#define per(i,a,n) for(int i=(n)-1;i>=(a);i--)
#define mp make_pair
#define pb push_back

typedef long double db;

template<class T> inline void cmin(T&x,T c){if(c<x)x=c;}
template<class T> inline void cmax(T&x,T c){if(c>x)x=c;}
 
const db EPS = 1e-8;
 
inline int sign(db a) {
    return a < -EPS ? -1 : a > EPS;
}
 
inline int cmp(db a, db b){
    return sign(a-b);
}
 
struct P {
    db x, y;
    P() {}
    P(db _x, db _y) : x(_x), y(_y) {}
    P operator+(P p) { return P(x + p.x, y + p.y); }
    P operator-(P p) { return P(x - p.x, y - p.y); }
    P operator*(db d) { return P(x * d, y * d); }
    P operator/(db d) { return P(x / d, y / d); }
    bool operator<(P p) const { 
        int c = cmp(x, p.x);
        if (c) return c == -1;
        return cmp(y, p.y) == -1;
    }
    db dot(P p) { return x * p.x + y * p.y; }
    db det(P p) { return x * p.y - y * p.x; }
    db distTo(P p) { return (*this-p).abs(); }
    db alpha() { return atan2(y, x); }
    void read() { cin>>x>>y; }
    db abs() { return sqrt(abs2());}
    db abs2() { return x * x + y * y; }
    P rot90() { return P(-y,x);}
    P unit() { return *this/abs(); }
};
 
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))

P isLL(P p1, P p2, P q1, P q2) {
    db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
    return (p1 * a2 + p2 * a1) / (a1 + a2);
}

bool crsLL(P p1, P p2, P q1, P q2){
    db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
    return sign(a1+a2) != 0;
}

bool isMiddle(db a, db m, db b) {
    return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}
  
bool isMiddle(P a, P m, P b) {
    return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}

bool onSeg(P p1, P p2, P q){
    return crossOp(p1,p2,q) == 0 && isMiddle(p1, q, p2);
}

P vs,vt;
int N,M;
vector<P> W,E;

int contain(vector<P> ps, P p){ //2:inside,1:on_seg,0:outside
    int n = ps.size(), ret = 0; 
    rep(i,0,n){
        P u=ps[i],v=ps[(i+1)%n];
        if(onSeg(u,v,p)) return 1;
        if(cmp(u.y,v.y)<=0) swap(u,v);
        if(cmp(p.y,u.y) >0 || cmp(p.y,v.y) <= 0) continue;
        ret ^= crossOp(p,u,v) > 0;
    }
    return ret*2;
}

bool check(vector<P> ps, P s, P t){
	vector<P> important;
	int n=ps.size();

	rep(i,0,n){
		P p1=ps[i],p2=ps[(i+1)%n];
		if(crsLL(p1,p2,s,t)){
			P q = isLL(p1,p2,s,t);
			if(isMiddle(s,q,t))
				important.pb(q);
		}
	}
	important.pb(s);
	important.pb(t);
	sort(important.begin(), important.end());

	rep(i,0,important.size() - 1){
		if((important[i] - important[i+1]).abs() > EPS){
			P p = (important[i] + important[i+1])/2;
			if(contain(ps,p) == 0) return 0;
		}
	}

	return 1;
}

db dijstra(vector<P> ps, P s, P t){
	vector<P> qs = ps;

	qs.pb(s);qs.pb(t);

	int n = qs.size();

	bool can[30][30] = {};
	db edge[30][30];
	rep(i,0,n) rep(j,0,i){
		can[i][j] = can[j][i] = check(ps,qs[i],qs[j]);
		edge[i][j] = edge[j][i] = (qs[i] - qs[j]).abs();
	}

	db dist[30] = {};
	bool used[30] = {};
	rep(i,0,n) dist[i] = 1e100;

	dist[n-2] = 0;

	rep(i,0,n){
		int u = -1;
		rep(i,0,n) if(!used[i] && (u == -1 || dist[i] < dist[u])) u = i;
		used[u] = 1;
		rep(i,0,n) if(can[u][i]){
			cmin(dist[i],dist[u] + edge[u][i]);
		}
	}

	return dist[n-1];
} 


P proj(P p1, P p2, P q) {
    P dir = p2 - p1;
    return p1 + dir * (dir.dot(q - p1) / dir.abs2());
}

db nearest(P p1,P p2,P q){
    P h = proj(p1,p2,q);
    if(isMiddle(p1,h,p2))
        return q.distTo(h);
    return min(p1.distTo(q),p2.distTo(q));
}

P nearestP(P p1,P p2,P q){
    P h = proj(p1,p2,q);
    if(isMiddle(p1,h,p2))
        return h;
    if(p1.distTo(q) < p2.distTo(q))
    	return p1;
    else
    	return p2;
}

db bridge,total;

void update(db br,db tot){
	if(abs(br-bridge) <= 1e-14){
		cmin(total,tot);
		return;
	}
	if(br < bridge){
		bridge = br;
		total = tot;
	}
}

P getP(P st, P dir, db dt){
	return st + dir * (dt - st.dot(dir));
}

void solve(P w1,P w2,P e1,P e2){
	// w1 -- w2
	// e1 -- e2

	//four cases
	rep(i,0,2){
		P me = i?w2:w1;
		P p = nearestP(e1,e2,me);
		update(p.distTo(me), dijstra(W,vs,me) + dijstra(E,p,vt));
	}

	rep(i,0,2){
		P me = i?e2:e1;
		P p = nearestP(w1,w2,me);
		update(p.distTo(me), dijstra(W,vs,p) + dijstra(E,me,vt));
	}

	//a special case
	if(sign((w2-w1).det(e2-e1)) == 0){
		P dir = (e2-e1).unit();
		if(w2.dot(dir) < w1.dot(dir)) swap(w1,w2);

		db l = max(e1.dot(dir),w1.dot(dir));
		db r = min(e2.dot(dir),w2.dot(dir));

		if(cmp(l,r) >= 0) return;

		auto calc = [w1,e1,dir](db x){
			P pW = getP(w1,dir,x);
			P pE = getP(e1,dir,x);
			return dijstra(W,vs,pW) + dijstra(E,pE,vt);
		};

		rep(it,0,100){
			db L = (l*2+r)/3, R = (l+2*r)/3;

			if(calc(L) < calc(R))
				r=R;
			else
				l=L;
		}

		update(getP(w1,dir,l).distTo(getP(e1,dir,l)), calc(l));
	}
}

int main(){
	vs.read();vt.read();
	cin>>N; W.resize(N); rep(i,0,N) W[i].read(); W.pb({0,1000}); W.pb({0,0});


	cin>>M; E.resize(M); rep(i,0,M) E[i].read(); E.pb({1000,1000}); E.pb({1000,0});

	bridge = 1e100; total = 1e100;

	rep(i,0,W.size()) rep(j,0,E.size()) solve(W[i],W[(i+1)%W.size()],E[i],E[(i+1)%E.size()]);

	printf("%0.10f %0.10f\n", (double)bridge, (double)(bridge + total));
}
accuracy: 0.0392156862745098
time_ms: 910
memory_kb: 3220
final_rank: 13

code_snippet: #include<bits/stdc++.h>
#define MAX 30
#define inf 1<<29
#define linf 1e16
#define eps (1e-8)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1)
#define phi (1.0+sqrt(5))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

bool isParallel(Vector a,Vector b){
  return equals(cross(a,b),0.0);
}

bool isParallel(Segment s,Segment t){
  return equals(cross(s.p1-s.p2,t.p1-t.p2),0.0);
}

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

bool intersect(Point p1,Point p2,Point p3,Point p4){
  return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0 &&
          ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}

bool intersect(Segment s1,Segment s2){
  return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}

Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

bool contains(Polygon p,Segment s){
  vector<pair<double,Point> > v;
  int n=p.size();
  v.push_back(make_pair(0,s.p1));
  v.push_back(make_pair(abs(s.p1-s.p2),s.p2));
  for(int i=0;i<n;i++){
    Segment e(p[i],p[(i+1)%n]);
    if(isParallel(s,e))continue;
    if(!intersect(s,e))continue;
    Point m=getCrossPointLL(s,e);
    v.push_back(make_pair(abs(m-s.p1),m));
  }
  sort(v.begin(),v.end());
  for(int i=0;i<v.size()-1;i++){
    Point m=v[i].s+(v[i+1].s-v[i].s)/2.0;
    if(contains(p,m)==0)return false;
  }
  return true;
}

pair<Point,Point> closest_pair(Segment a,Segment b){
  pair<Point,Point> res(a.p1,b.p1);
  if(abs(a.p1-b.p2)<abs(res.f-res.s))res=mp(a.p1,b.p2);
  if(abs(a.p2-b.p1)<abs(res.f-res.s))res=mp(a.p2,b.p1);
  if(abs(a.p2-b.p2)<abs(res.f-res.s))res=mp(a.p2,b.p2);
  Point c;
  c=project(b,a.p1);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p1)<abs(res.f-res.s))res=mp(a.p1,c);
  c=project(b,a.p2);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p2)<abs(res.f-res.s))res=mp(a.p2,c);
  c=project(a,b.p1);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p1)<abs(res.f-res.s))res=mp(b.p1,c);
  c=project(a,b.p2);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p2)<abs(res.f-res.s))res=mp(b.p2,c);
  return res;
}

int n,m;
Point s,t;
vector<Point> w,e;
Polygon W,E,WE;
vector<Point> vp[2];
vector<pid> g[2][MAX];

void add_edge(int ind,int to,int from,double cost){
  g[ind][to].pb(mp(from,cost));
  g[ind][from].pb(mp(to,cost));
}

double dijkstra(Point a){
  int ind=-1;
  Polygon p;
  if(contains(W,a)){ ind=0;p=W; }
  else { ind=1;p=E; }
  int start=vp[ind].size();
  g[ind][start].clear();
  FOR(i,0,vp[ind].size())
    if(contains(p,Segment(vp[ind][i],a)))
       g[ind][start].pb(mp(i,abs(a-vp[ind][i])));

  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[start]=0;
  pq.push(mp(0,start));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]<u.f)continue;
    if(u.s==0)return d[u.s];

    FOR(i,0,g[ind][u.s].size()){
      int next=g[ind][u.s][i].f;
      double cost=g[ind][u.s][i].s+d[u.s];
      if(cost<d[next]){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

void make_graphs(){
  W.pb(Point(0,1000));
  W.pb(Point(0,0));
  FOR(i,0,n)W.pb(w[i]);
  E.pb(Point(1000,0));
  E.pb(Point(1000,1000));
  RFOR(i,m,0)E.pb(e[i]);

  vp[0].pb(s);
  FOR(i,0,W.size())vp[0].pb(W[i]);
  FOR(i,0,vp[0].size()){
    FOR(j,i+1,vp[0].size()){
      if(contains(W,Segment(vp[0][i],vp[0][j])))
        add_edge(0,i,j,abs(vp[0][i]-vp[0][j]));
    }
  }
  vp[1].pb(t);
  FOR(i,0,E.size())vp[1].pb(E[i]);
  FOR(i,0,vp[1].size()){
    FOR(j,i+1,vp[1].size()){
      if(contains(E,Segment(vp[1][i],vp[1][j])))
        add_edge(1,i,j,abs(vp[1][i]-vp[1][j]));
    }
  }
}

pdd check(Segment a,Segment b){
  pdd res(inf,inf);
  if(a.p2.y<a.p1.y)return res;
  if(b.p2.y<b.p1.y)return res;
  if(isParallel(a,b)){
    Segment seg=a;
    Point c;
    bool flag=false;
    c=project(a,b.p1);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p1=c;flag=true; }
    c=project(a,b.p2);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p2=c;flag=true; }
    if(flag){
      Vector v=seg.p2-seg.p1;
      v=v/abs(v);
      double L=0,R=abs(seg.p1-seg.p2);
      FOR(k,0,50){
        double m1=(L*phi+R)/(1.0+phi);
        double m2=(L+R*phi)/(1.0+phi);
        Point p1,p2;
        p1=seg.p1+v*m1;
        p2=project(b,p1);
        double res1=dijkstra(p1)+dijkstra(p2);
        p1=seg.p1+v*m2;
        p2=project(b,p1);
        double res2=dijkstra(p1)+dijkstra(p2);
        if(res1<res2)R=m2;
        else L=m1;
      }
      Point p1=seg.p1+v*L,p2=project(b,p1);
      res.f=abs(p1-p2);
      res.s=dijkstra(seg.p1+v*L)+dijkstra(project(b,seg.p1+v*L));
      return res;
    }
  }
  pair<Point,Point> pp=closest_pair(a,b);
  res.f=abs(pp.f-pp.s);
  res.s=dijkstra(pp.f)+dijkstra(pp.s);
  return res;
}

bool comp(pdd a,pdd b){
  return fabs((a.f)-(b.f))<Eps ? b.s-a.s<-Eps : b.f-a.f<-Eps;
}

void solve(){
  make_graphs();
  pdd res(inf,inf);
  FOR(i,0,n-1){
    Segment s1(w[i],w[i+1]);
    FOR(j,0,m-1){
      Segment s2(e[j],e[j+1]);
      pdd tmp=check(s1,s2);
      if(comp(res,tmp))res=tmp;
    }
  }
  printf("%.10f %.10f\n",res.f,res.f+res.s);
}

int main()
{
  cin>>s.x>>s.y>>t.x>>t.y;
  cin>>n;
  w.resize(n);
  FOR(i,0,n)cin>>w[i].x>>w[i].y;
  cin>>m;
  e.resize(m);
  FOR(i,0,m)cin>>e[i].x>>e[i].y;
  solve();
  return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 3288
final_rank: 2

code_snippet: #include<bits/stdc++.h>
#define MAX 30
#define inf 1<<29
#define linf 1e16
#define eps (1e-8)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1)
#define phi (1.0+sqrt(5))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

bool isParallel(Vector a,Vector b){
  return equals(cross(a,b),0.0);
}

bool isParallel(Segment s,Segment t){
  return equals(cross(s.p1-s.p2,t.p1-t.p2),0.0);
}

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

bool intersect(Point p1,Point p2,Point p3,Point p4){
  return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0 &&
          ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}

bool intersect(Segment s1,Segment s2){
  return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}

Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

bool contains(Polygon p,Segment s){
  vector<pair<double,Point> > v;
  int n=p.size();
  v.push_back(make_pair(0,s.p1));
  v.push_back(make_pair(abs(s.p1-s.p2),s.p2));
  for(int i=0;i<n;i++){
    Segment e(p[i],p[(i+1)%n]);
    if(isParallel(s,e))continue;
    if(!intersect(s,e))continue;
    Point m=getCrossPointLL(s,e);
    v.push_back(make_pair(abs(m-s.p1),m));
  }
  sort(v.begin(),v.end());
  for(int i=0;i<v.size()-1;i++){
    Point m=v[i].s+(v[i+1].s-v[i].s)/2.0;
    if(contains(p,m)==0)return false;
  }
  return true;
}

pair<Point,Point> closest_pair(Segment a,Segment b){
  pair<Point,Point> res(a.p1,b.p1);
  if(abs(a.p1-b.p2)<abs(res.f-res.s))res=mp(a.p1,b.p2);
  if(abs(a.p2-b.p1)<abs(res.f-res.s))res=mp(a.p2,b.p1);
  if(abs(a.p2-b.p2)<abs(res.f-res.s))res=mp(a.p2,b.p2);
  Point c;
  c=project(b,a.p1);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p1)<abs(res.f-res.s))res=mp(a.p1,c);
  c=project(b,a.p2);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p2)<abs(res.f-res.s))res=mp(a.p2,c);
  c=project(a,b.p1);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p1)<abs(res.f-res.s))res=mp(b.p1,c);
  c=project(a,b.p2);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p2)<abs(res.f-res.s))res=mp(b.p2,c);
  return res;
}

int n,m;
Point s,t;
vector<Point> w,e;
Polygon W,E,WE;
vector<Point> vp[2];
vector<pid> g[2][MAX];

void add_edge(int ind,int to,int from,double cost){
  g[ind][to].pb(mp(from,cost));
  g[ind][from].pb(mp(to,cost));
}

double dijkstra(Point a){
  int ind=-1;
  Polygon p;
  if(contains(W,a)){ ind=0;p=W; }
  else { ind=1;p=E; }
  int start=vp[ind].size();
  g[ind][start].clear();
  FOR(i,0,vp[ind].size())
    if(contains(p,Segment(vp[ind][i],a)))
       g[ind][start].pb(mp(i,abs(a-vp[ind][i])));

  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[start]=0;
  pq.push(mp(0,start));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]<u.f)continue;
    if(u.s==0)return d[u.s];

    FOR(i,0,g[ind][u.s].size()){
      int next=g[ind][u.s][i].f;
      double cost=g[ind][u.s][i].s+d[u.s];
      if(cost<d[next]){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

void make_graphs(){
  W.pb(Point(0,1000));
  W.pb(Point(0,0));
  FOR(i,0,n)W.pb(w[i]);
  E.pb(Point(1000,0));
  E.pb(Point(1000,1000));
  RFOR(i,m,0)E.pb(e[i]);

  vp[0].pb(s);
  FOR(i,0,W.size())vp[0].pb(W[i]);
  FOR(i,0,vp[0].size()){
    FOR(j,i+1,vp[0].size()){
      if(contains(W,Segment(vp[0][i],vp[0][j])))
        add_edge(0,i,j,abs(vp[0][i]-vp[0][j]));
    }
  }
  vp[1].pb(t);
  FOR(i,0,E.size())vp[1].pb(E[i]);
  FOR(i,0,vp[1].size()){
    FOR(j,i+1,vp[1].size()){
      if(contains(E,Segment(vp[1][i],vp[1][j])))
        add_edge(1,i,j,abs(vp[1][i]-vp[1][j]));
    }
  }
}

pdd check(Segment a,Segment b){
  pdd res(inf,inf);
  if(isParallel(a,b)){
    Segment seg=a;
    Point c;
    bool flag=false;
    c=project(a,b.p1);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p1=c;flag=true; }
    c=project(a,b.p2);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p2=c;flag=true; }
    if(flag){
      Vector v=seg.p2-seg.p1;
      v=v/abs(v);
      double L=0,R=abs(seg.p1-seg.p2);
      FOR(k,0,50){
        double m1=(L*phi+R)/(1.0+phi);
        double m2=(L+R*phi)/(1.0+phi);
        Point p1,p2;
        p1=seg.p1+v*m1;
        p2=project(b,p1);
        double res1=dijkstra(p1)+dijkstra(p2);
        p1=seg.p1+v*m2;
        p2=project(b,p1);
        double res2=dijkstra(p1)+dijkstra(p2);
        if(res1<res2)R=m2;
        else L=m1;
      }
      Point p1=seg.p1+v*L,p2=project(b,p1);
      res.f=abs(p1-p2);
      res.s=dijkstra(seg.p1+v*L)+dijkstra(project(b,seg.p1+v*L));
      return res;
    }
  }
  pair<Point,Point> pp=closest_pair(a,b);
  res.f=abs(pp.f-pp.s);
  res.s=dijkstra(pp.f)+dijkstra(pp.s);
  return res;
}

bool comp(pdd a,pdd b){
  return fabs((a.f)-(b.f))<Eps ? b.s-a.s<-Eps : b.f-a.f<-Eps;
}

void solve(){
  make_graphs();
  pdd res(inf,inf);
  FOR(i,0,n-1){
    Segment s1(w[i],w[i+1]);
    FOR(j,0,m-1){
      Segment s2(e[j],e[j+1]);
      pdd tmp=check(s1,s2);
      if(comp(res,tmp))res=tmp;
    }
  }
  printf("%.10f %.10f\n",res.f,res.f+res.s);
}

int main()
{
  cin>>s.x>>s.y>>t.x>>t.y;
  cin>>n;
  w.resize(n);
  FOR(i,0,n)cin>>w[i].x>>w[i].y;
  cin>>m;
  e.resize(m);
  FOR(i,0,m)cin>>e[i].x>>e[i].y;
  solve();
  return 0;
}
accuracy: 1
time_ms: 280
memory_kb: 3284
final_rank: 1

code_snippet: #include<bits/stdc++.h>
#define MAX 30
#define inf 1<<29
#define linf 1e16
#define eps (1e-8)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1)
#define phi (1.0+sqrt(5))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

bool isParallel(Vector a,Vector b){
  return equals(cross(a,b),0.0);
}

bool isParallel(Segment s,Segment t){
  return equals(cross(s.p1-s.p2,t.p1-t.p2),0.0);
}

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

bool intersect(Point p1,Point p2,Point p3,Point p4){
  return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0 &&
          ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}

bool intersect(Segment s1,Segment s2){
  return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}

Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

bool contains(Polygon p,Segment s){
  vector<pair<double,Point> > v;
  int n=p.size();
  v.push_back(make_pair(0,s.p1));
  v.push_back(make_pair(abs(s.p1-s.p2),s.p2));
  for(int i=0;i<n;i++){
    Segment e(p[i],p[(i+1)%n]);
    if(isParallel(s,e))continue;
    if(!intersect(s,e))continue;
    Point m=getCrossPointLL(s,e);
    v.push_back(make_pair(abs(m-s.p1),m));
  }
  sort(v.begin(),v.end());
  for(int i=0;i<v.size()-1;i++){
    Point m=v[i].s+(v[i+1].s-v[i].s)/2.0;
    if(contains(p,m)==0)return false;
  }
  return true;
}

pair<Point,Point> closest_pair(Segment a,Segment b){
  pair<Point,Point> res(a.p1,b.p1);
  if(abs(a.p1-b.p2)<abs(res.f-res.s))res=mp(a.p1,b.p2);
  if(abs(a.p2-b.p1)<abs(res.f-res.s))res=mp(a.p2,b.p1);
  if(abs(a.p2-b.p2)<abs(res.f-res.s))res=mp(a.p2,b.p2);
  Point c;
  c=project(b,a.p1);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p1)<abs(res.f-res.s))res=mp(a.p1,c);
  c=project(b,a.p2);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p2)<abs(res.f-res.s))res=mp(a.p2,c);
  c=project(a,b.p1);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p1)<abs(res.f-res.s))res=mp(b.p1,c);
  c=project(a,b.p2);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p2)<abs(res.f-res.s))res=mp(b.p2,c);
  return res;
}

int n,m;
Point s,t;
vector<Point> w,e;
Polygon W,E,WE;
vector<Point> vp[2];
vector<pid> g[2][MAX];

void add_edge(int ind,int to,int from,double cost){
  g[ind][to].pb(mp(from,cost));
  g[ind][from].pb(mp(to,cost));
}

double dijkstra(Point a){
  int ind=-1;
  Polygon p;
  if(contains(W,a)){ ind=0;p=W; }
  else { ind=1;p=E; }
  int start=vp[ind].size();
  g[ind][start].clear();
  FOR(i,0,vp[ind].size())
    if(contains(p,Segment(vp[ind][i],a)))
       g[ind][start].pb(mp(i,abs(a-vp[ind][i])));

  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[start]=0;
  pq.push(mp(0,start));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]<u.f)continue;
    if(u.s==0)return d[u.s];

    FOR(i,0,g[ind][u.s].size()){
      int next=g[ind][u.s][i].f;
      double cost=g[ind][u.s][i].s+d[u.s];
      if(cost<d[next]){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

void make_graphs(){
  W.pb(Point(0,1000));
  W.pb(Point(0,0));
  FOR(i,0,n)W.pb(w[i]);
  E.pb(Point(1000,0));
  E.pb(Point(1000,1000));
  RFOR(i,m,0)E.pb(e[i]);

  vp[0].pb(s);
  FOR(i,0,W.size())vp[0].pb(W[i]);
  FOR(i,0,vp[0].size()){
    FOR(j,i+1,vp[0].size()){
      if(contains(W,Segment(vp[0][i],vp[0][j])))
        add_edge(0,i,j,abs(vp[0][i]-vp[0][j]));
    }
  }
  vp[1].pb(t);
  FOR(i,0,E.size())vp[1].pb(E[i]);
  FOR(i,0,vp[1].size()){
    FOR(j,i+1,vp[1].size()){
      if(contains(E,Segment(vp[1][i],vp[1][j])))
        add_edge(1,i,j,abs(vp[1][i]-vp[1][j]));
    }
  }
}

pdd check(Segment a,Segment b){
  pdd res(inf,inf);
  if(isParallel(a,b)){
    Segment seg=a;
    Point c;
    bool flag=false;
    c=project(a,b.p1);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p1=c;flag=true; }
    c=project(a,b.p2);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p2=c;flag=true; }
    if(flag){
      Vector v=seg.p2-seg.p1;
      v=v/abs(v);
      double L=0,R=abs(seg.p1-seg.p2);
      FOR(k,0,100){
        double m1=(L*phi+R)/(1.0+phi);
        double m2=(L+R*phi)/(1.0+phi);
        Point p1,p2;
        p1=seg.p1+v*m1;
        p2=project(b,p1);
        double res1=dijkstra(p1)+dijkstra(p2);
        p1=seg.p1+v*m2;
        p2=project(b,p1);
        double res2=dijkstra(p1)+dijkstra(p2);
        if(res1<res2)R=m2;
        else L=m1;
      }
      Point p1=seg.p1+v*L,p2=project(b,p1);
      res.f=abs(p1-p2);
      res.s=dijkstra(seg.p1+v*L)+dijkstra(project(b,seg.p1+v*L));
      return res;
    }
  }
  pair<Point,Point> pp=closest_pair(a,b);
  res.f=abs(pp.f-pp.s);
  res.s=dijkstra(pp.f)+dijkstra(pp.s);
  return res;
}

bool comp(pdd a,pdd b){
  return fabs((a.f)-(b.f))<Eps ? b.s-a.s<-Eps : b.f-a.f<-Eps;
}

void solve(){
  make_graphs();
  pdd res(inf,inf);
  FOR(i,0,n-1){
    Segment s1(w[i],w[i+1]);
    FOR(j,0,m-1){
      Segment s2(e[j],e[j+1]);
      pdd tmp=check(s1,s2);
      if(comp(res,tmp))res=tmp;
    }
  }
  printf("%.10f %.10f\n",res.f,res.f+res.s);
}

int main()
{
  cin>>s.x>>s.y>>t.x>>t.y;
  cin>>n;
  w.resize(n);
  FOR(i,0,n)cin>>w[i].x>>w[i].y;
  cin>>m;
  e.resize(m);
  FOR(i,0,m)cin>>e[i].x>>e[i].y;
  solve();
  return 0;
}
accuracy: 1
time_ms: 570
memory_kb: 3284
final_rank: 3

code_snippet: #include<bits/stdc++.h>
#define MAX 30
#define inf 1<<29
#define linf 1e16
#define eps (1e-8)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1)
#define phi (1.0+sqrt(5))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

bool isParallel(Vector a,Vector b){
  return equals(cross(a,b),0.0);
}

bool isParallel(Segment s,Segment t){
  return equals(cross(s.p1-s.p2,t.p1-t.p2),0.0);
}

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

bool intersect(Point p1,Point p2,Point p3,Point p4){
  return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0 &&
          ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}

bool intersect(Segment s1,Segment s2){
  return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}

Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

bool contains(Polygon p,Segment s){
  vector<pair<double,Point> > v;
  int n=p.size();
  v.push_back(make_pair(0,s.p1));
  v.push_back(make_pair(abs(s.p1-s.p2),s.p2));
  for(int i=0;i<n;i++){
    Segment e(p[i],p[(i+1)%n]);
    if(isParallel(s,e))continue;
    if(!intersect(s,e))continue;
    Point m=getCrossPointLL(s,e);
    v.push_back(make_pair(abs(m-s.p1),m));
  }
  sort(v.begin(),v.end());
  for(int i=0;i<v.size()-1;i++){
    Point m=v[i].s+(v[i+1].s-v[i].s)/2.0;
    if(contains(p,m)==0)return false;
  }
  return true;
}

pair<Point,Point> closest_pair(Segment a,Segment b){
  pair<Point,Point> res(a.p1,b.p1);
  if(abs(a.p1-b.p2)<abs(res.f-res.s))res=mp(a.p1,b.p2);
  if(abs(a.p2-b.p1)<abs(res.f-res.s))res=mp(a.p2,b.p1);
  if(abs(a.p2-b.p2)<abs(res.f-res.s))res=mp(a.p2,b.p2);
  Point c;
  c=project(b,a.p1);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p1)<abs(res.f-res.s))res=mp(a.p1,c);
  c=project(b,a.p2);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p2)<abs(res.f-res.s))res=mp(a.p2,c);
  c=project(a,b.p1);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p1)<abs(res.f-res.s))res=mp(b.p1,c);
  c=project(a,b.p2);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p2)<abs(res.f-res.s))res=mp(b.p2,c);
  return res;
}

int n,m;
Point s,t;
vector<Point> w,e;
Polygon W,E,WE;
vector<Point> vp[2];
vector<pid> g[2][MAX];

void add_edge(int ind,int to,int from,double cost){
  g[ind][to].pb(mp(from,cost));
  g[ind][from].pb(mp(to,cost));
}

double dijkstra(Point a){
  int ind=-1;
  Polygon p;
  if(contains(W,a)){ ind=0;p=W; }
  else { ind=1;p=E; }
  int start=vp[ind].size();
  g[ind][start].clear();
  FOR(i,0,vp[ind].size())
    if(contains(p,Segment(vp[ind][i],a)))
       g[ind][start].pb(mp(i,abs(a-vp[ind][i])));

  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[start]=0;
  pq.push(mp(0,start));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]<u.f)continue;
    if(u.s==0)return d[u.s];

    FOR(i,0,g[ind][u.s].size()){
      int next=g[ind][u.s][i].f;
      double cost=g[ind][u.s][i].s+d[u.s];
      if(cost<d[next]){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

void make_graphs(){
  W.pb(Point(0,1000));
  W.pb(Point(0,0));
  FOR(i,0,n)W.pb(w[i]);
  E.pb(Point(1000,0));
  E.pb(Point(1000,1000));
  RFOR(i,m,0)E.pb(e[i]);

  vp[0].pb(s);
  FOR(i,0,W.size())vp[0].pb(W[i]);
  FOR(i,0,vp[0].size()){
    FOR(j,i+1,vp[0].size()){
      if(contains(W,Segment(vp[0][i],vp[0][j])))
        add_edge(0,i,j,abs(vp[0][i]-vp[0][j]));
    }
  }
  vp[1].pb(t);
  FOR(i,0,E.size())vp[1].pb(E[i]);
  FOR(i,0,vp[1].size()){
    FOR(j,i+1,vp[1].size()){
      if(contains(E,Segment(vp[1][i],vp[1][j])))
        add_edge(1,i,j,abs(vp[1][i]-vp[1][j]));
    }
  }
}

pdd check(Segment a,Segment b){
  pdd res(inf,inf);
  if(isParallel(a,b)){
    Segment seg=a;
    Point c;
    bool flag=false;
    c=project(a,b.p1);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p1=c;flag=true; }
    c=project(a,b.p2);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p2=c;flag=true; }
    if(flag){
      Vector v=seg.p2-seg.p1;
      v=v/abs(v);
      double L=0,R=abs(seg.p1-seg.p2);
      FOR(k,0,200){
        double m1=(L*phi+R)/(1.0+phi);
        double m2=(L+R*phi)/(1.0+phi);
        Point p1,p2;
        p1=seg.p1+v*m1;
        p2=project(b,p1);
        double res1=dijkstra(p1)+dijkstra(p2);
        p1=seg.p1+v*m2;
        p2=project(b,p1);
        double res2=dijkstra(p1)+dijkstra(p2);
        if(res1<res2)R=m2;
        else L=m1;
      }
      Point p1=seg.p1+v*L,p2=project(b,p1);
      res.f=abs(p1-p2);
      res.s=dijkstra(seg.p1+v*L)+dijkstra(project(b,seg.p1+v*L));
      return res;
    }
  }
  pair<Point,Point> pp=closest_pair(a,b);
  res.f=abs(pp.f-pp.s);
  res.s=dijkstra(pp.f)+dijkstra(pp.s);
  return res;
}

bool comp(pdd a,pdd b){
  return fabs((a.f)-(b.f))<Eps ? b.s-a.s<-Eps : b.f-a.f<-Eps;
}

void solve(){
  make_graphs();
  pdd res(inf,inf);
  FOR(i,0,n-1){
    Segment s1(w[i],w[i+1]);
    FOR(j,0,m-1){
      Segment s2(e[j],e[j+1]);
      pdd tmp=check(s1,s2);
      if(comp(res,tmp))res=tmp;
    }
  }
  printf("%.10f %.10f\n",res.f,res.f+res.s);
}

int main()
{
  cin>>s.x>>s.y>>t.x>>t.y;
  cin>>n;
  w.resize(n);
  FOR(i,0,n)cin>>w[i].x>>w[i].y;
  cin>>m;
  e.resize(m);
  FOR(i,0,m)cin>>e[i].x>>e[i].y;
  solve();
  return 0;
}
accuracy: 1
time_ms: 1270
memory_kb: 3284
final_rank: 5

code_snippet: #include<bits/stdc++.h>
#define MAX 30
#define inf 1<<29
#define linf 1e16
#define eps (1e-8)
#define Eps (1e-20)
#define mod 1000000007
#define pi acos(-1)
#define phi (1.0+sqrt(5))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

bool isParallel(Vector a,Vector b){
  return equals(cross(a,b),0.0);
}

bool isParallel(Segment s,Segment t){
  return equals(cross(s.p1-s.p2,t.p1-t.p2),0.0);
}

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

bool intersect(Point p1,Point p2,Point p3,Point p4){
  return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0 &&
          ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}

bool intersect(Segment s1,Segment s2){
  return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}

Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

bool contains(Polygon p,Segment s){
  vector<pair<double,Point> > v;
  int n=p.size();
  v.push_back(make_pair(0,s.p1));
  v.push_back(make_pair(abs(s.p1-s.p2),s.p2));
  for(int i=0;i<n;i++){
    Segment e(p[i],p[(i+1)%n]);
    if(isParallel(s,e))continue;
    if(!intersect(s,e))continue;
    Point m=getCrossPointLL(s,e);
    v.push_back(make_pair(abs(m-s.p1),m));
  }
  sort(v.begin(),v.end());
  for(int i=0;i<v.size()-1;i++){
    Point m=v[i].s+(v[i+1].s-v[i].s)/2.0;
    if(contains(p,m)==0)return false;
  }
  return true;
}

pair<Point,Point> closest_pair(Segment a,Segment b){
  pair<Point,Point> res(a.p1,b.p1);
  if(abs(a.p1-b.p2)<abs(res.f-res.s))res=mp(a.p1,b.p2);
  if(abs(a.p2-b.p1)<abs(res.f-res.s))res=mp(a.p2,b.p1);
  if(abs(a.p2-b.p2)<abs(res.f-res.s))res=mp(a.p2,b.p2);
  Point c;
  c=project(b,a.p1);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p1)<abs(res.f-res.s))res=mp(a.p1,c);
  c=project(b,a.p2);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p2)<abs(res.f-res.s))res=mp(a.p2,c);
  c=project(a,b.p1);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p1)<abs(res.f-res.s))res=mp(b.p1,c);
  c=project(a,b.p2);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p2)<abs(res.f-res.s))res=mp(b.p2,c);
  return res;
}

int n,m;
Point s,t;
vector<Point> w,e;
Polygon W,E,WE;
vector<Point> vp[2];
vector<pid> g[2][MAX];

void add_edge(int ind,int to,int from,double cost){
  g[ind][to].pb(mp(from,cost));
  g[ind][from].pb(mp(to,cost));
}

double dijkstra(Point a){
  int ind=-1;
  Polygon p;
  if(contains(W,a)){ ind=0;p=W; }
  else { ind=1;p=E; }
  int start=vp[ind].size();
  g[ind][start].clear();
  FOR(i,0,vp[ind].size())
    if(contains(p,Segment(vp[ind][i],a)))
       g[ind][start].pb(mp(i,abs(a-vp[ind][i])));

  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[start]=0;
  pq.push(mp(0,start));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]<u.f)continue;
    if(u.s==0)return d[u.s];

    FOR(i,0,g[ind][u.s].size()){
      int next=g[ind][u.s][i].f;
      double cost=g[ind][u.s][i].s+d[u.s];
      if(cost<d[next]){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

void make_graphs(){
  W.pb(Point(0,1000));
  W.pb(Point(0,0));
  FOR(i,0,n)W.pb(w[i]);
  E.pb(Point(1000,0));
  E.pb(Point(1000,1000));
  RFOR(i,m,0)E.pb(e[i]);

  vp[0].pb(s);
  FOR(i,0,W.size())vp[0].pb(W[i]);
  FOR(i,0,vp[0].size()){
    FOR(j,i+1,vp[0].size()){
      if(contains(W,Segment(vp[0][i],vp[0][j])))
        add_edge(0,i,j,abs(vp[0][i]-vp[0][j]));
    }
  }
  vp[1].pb(t);
  FOR(i,0,E.size())vp[1].pb(E[i]);
  FOR(i,0,vp[1].size()){
    FOR(j,i+1,vp[1].size()){
      if(contains(E,Segment(vp[1][i],vp[1][j])))
        add_edge(1,i,j,abs(vp[1][i]-vp[1][j]));
    }
  }
}

pdd check(Segment a,Segment b){
  pdd res(inf,inf);
//  if(a.p1.y<a.p2.y)return res;
//  if(b.p1.y<b.p2.y)return res;
  if(isParallel(a,b)){
    Segment seg=a;
    Point c;
    bool flag=false;
    c=project(a,b.p1);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p1=c;flag=true; }
    c=project(a,b.p2);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p2=c;flag=true; }
    if(flag){
      Vector v=seg.p2-seg.p1;
      v=v/abs(v);
      double L=0,R=abs(seg.p1-seg.p2);
      FOR(k,0,200){
        double m1=(L*phi+R)/(1.0+phi);
        double m2=(L+R*phi)/(1.0+phi);
        Point p1,p2;
        p1=seg.p1+v*m1;
        p2=project(b,p1);
        double res1=dijkstra(p1)+dijkstra(p2);
        p1=seg.p1+v*m2;
        p2=project(b,p1);
        double res2=dijkstra(p1)+dijkstra(p2);
        if(res1<res2)R=m2;
        else L=m1;
      }
      Point p1=seg.p1+v*L,p2=project(b,p1);
      res.f=abs(p1-p2);
      res.s=dijkstra(seg.p1+v*L)+dijkstra(project(b,seg.p1+v*L));
      return res;
    }
  }
  pair<Point,Point> pp=closest_pair(a,b);
  res.f=abs(pp.f-pp.s);
  res.s=dijkstra(pp.f)+dijkstra(pp.s);
  return res;
}

bool comp(pdd a,pdd b){
  return fabs((a.f)-(b.f))<Eps ? b.s-a.s<-Eps : b.f-a.f<-Eps;
}

void solve(){
  make_graphs();
  pdd res(inf,inf);
  FOR(i,0,n-1){
    Segment s1(w[i],w[i+1]);
    FOR(j,0,m-1){
      Segment s2(e[j],e[j+1]);
      pdd tmp=check(s1,s2);
      if(comp(res,tmp))res=tmp;
    }
  }
  printf("%.10f %.10f\n",res.f,res.f+res.s);
}

int main()
{
  cin>>s.x>>s.y>>t.x>>t.y;
  cin>>n;
  w.resize(n);
  FOR(i,0,n)cin>>w[i].x>>w[i].y;
  cin>>m;
  e.resize(m);
  FOR(i,0,m)cin>>e[i].x>>e[i].y;
  solve();
  return 0;
}
accuracy: 0.9019607843137255
time_ms: 1120
memory_kb: 3288
final_rank: 11

code_snippet: #include<bits/stdc++.h>
#define MAX 30
#define inf 1<<29
#define linf 1e16
#define eps (1e-10)
#define mod 1000000007
#define pi acos(-1)
#define phi (1.0+sqrt(5))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

bool isParallel(Vector a,Vector b){
  return equals(cross(a,b),0.0);
}

bool isParallel(Segment s,Segment t){
  return equals(cross(s.p1-s.p2,t.p1-t.p2),0.0);
}

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}

bool intersect(Point p1,Point p2,Point p3,Point p4){
  return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0 &&
          ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}

bool intersect(Segment s1,Segment s2){
  return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}

Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Vector a=g[i]-p,b=g[(i+1)%n]-p;
    if(abs(cross(a,b))<eps && dot(a,b)<eps)return 1;
    if(a.y>b.y)swap(a,b);
    if(a.y<eps && eps<b.y && cross(a,b)>eps)x=!x;
  }
  if(x)return 2;
  return 0;
}

bool contains(Polygon p,Segment s){
  vector<pair<double,Point> > v;
  int n=p.size();
  v.push_back(make_pair(0,s.p1));
  v.push_back(make_pair(abs(s.p1-s.p2),s.p2));
  for(int i=0;i<n;i++){
    Segment e(p[i],p[(i+1)%n]);
    if(isParallel(s,e))continue;
    if(!intersect(s,e))continue;
    Point m=getCrossPointLL(s,e);
    v.push_back(make_pair(abs(m-s.p1),m));
  }
  sort(v.begin(),v.end());
  for(int i=0;i<v.size()-1;i++){
    Point m=v[i].s+(v[i+1].s-v[i].s)/2.0;
    if(contains(p,m)==0)return false;
  }
  return true;
}

pair<Point,Point> closest_pair(Segment a,Segment b){
  pair<Point,Point> res(a.p1,b.p1);
  if(abs(a.p1-b.p2)<abs(res.f-res.s))res=mp(a.p1,b.p2);
  if(abs(a.p2-b.p1)<abs(res.f-res.s))res=mp(a.p2,b.p1);
  if(abs(a.p2-b.p2)<abs(res.f-res.s))res=mp(a.p2,b.p2);
  Point c;
  c=project(b,a.p1);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p1)<abs(res.f-res.s))res=mp(a.p1,c);
  c=project(b,a.p2);
  if(ccw(b.p1,b.p2,c)==0 &&
     abs(c-a.p2)<abs(res.f-res.s))res=mp(a.p2,c);
  c=project(a,b.p1);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p1)<abs(res.f-res.s))res=mp(b.p1,c);
  c=project(a,b.p2);
  if(ccw(a.p1,a.p2,c)==0 &&
     abs(c-b.p2)<abs(res.f-res.s))res=mp(b.p2,c);
  return res;
}

int n,m;
Point s,t;
vector<Point> w,e;
Polygon W,E,WE;
vector<Point> vp[2];
vector<pid> g[2][MAX];

void add_edge(int ind,int to,int from,double cost){
  g[ind][to].pb(mp(from,cost));
  g[ind][from].pb(mp(to,cost));
}

double dijkstra(Point a){
  int ind=-1;
  Polygon p;
  if(contains(W,a)){ ind=0;p=W; }
  else { ind=1;p=E; }
  int start=vp[ind].size();
  g[ind][start].clear();
  FOR(i,0,vp[ind].size())
    if(contains(p,Segment(vp[ind][i],a)))
       g[ind][start].pb(mp(i,abs(a-vp[ind][i])));

  double d[MAX];
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  fill(d,d+MAX,inf);
  d[start]=0;
  pq.push(mp(0,start));

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]<u.f)continue;
    if(u.s==0)return d[u.s];

    FOR(i,0,g[ind][u.s].size()){
      int next=g[ind][u.s][i].f;
      double cost=g[ind][u.s][i].s+d[u.s];
      if(cost<d[next]){
        d[next]=cost;
        pq.push(mp(cost,next));
      }
    }
  }
  return inf;
}

void make_graphs(){
  W.pb(Point(0,1000));
  W.pb(Point(0,0));
  FOR(i,0,n)W.pb(w[i]);
  E.pb(Point(1000,0));
  E.pb(Point(1000,1000));
  RFOR(i,m,0)E.pb(e[i]);

  vp[0].pb(s);
  FOR(i,0,W.size())vp[0].pb(W[i]);
  FOR(i,0,vp[0].size()){
    FOR(j,i+1,vp[0].size()){
      if(contains(W,Segment(vp[0][i],vp[0][j])))
        add_edge(0,i,j,abs(vp[0][i]-vp[0][j]));
    }
  }
  vp[1].pb(t);
  FOR(i,0,E.size())vp[1].pb(E[i]);
  FOR(i,0,vp[1].size()){
    FOR(j,i+1,vp[1].size()){
      if(contains(E,Segment(vp[1][i],vp[1][j])))
        add_edge(1,i,j,abs(vp[1][i]-vp[1][j]));
    }
  }
}

pdd check(Segment a,Segment b){
  pdd res(inf,inf);
//  if(a.p1.y<a.p2.y)return res;
//  if(b.p1.y<b.p2.y)return res;
  if(isParallel(a,b)){
    Segment seg=a;
    Point c;
    bool flag=false;
    c=project(a,b.p1);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p1=c;flag=true; }
    c=project(a,b.p2);
    if(ccw(seg.p1,seg.p2,c)==0){ seg.p2=c;flag=true; }
    if(flag){
      Vector v=seg.p2-seg.p1;
      v=v/abs(v);
      double L=0,R=abs(seg.p1-seg.p2);
      FOR(k,0,100){
        double m1=(L*phi+R)/(1.0+phi);
        double m2=(L+R*phi)/(1.0+phi);
        Point p1,p2;
        p1=seg.p1+v*m1;
        p2=project(b,p1);
        double res1=dijkstra(p1)+dijkstra(p2);
        p1=seg.p1+v*m2;
        p2=project(b,p1);
        double res2=dijkstra(p1)+dijkstra(p2);
        if(res1<res2)R=m2;
        else L=m1;
      }
      Point p1=seg.p1+v*L,p2=project(b,p1);
      res.f=abs(p1-p2);
      res.s=dijkstra(seg.p1+v*L)+dijkstra(project(b,seg.p1+v*L));
      return res;
    }
  }
  pair<Point,Point> pp=closest_pair(a,b);
  res.f=abs(pp.f-pp.s);
  res.s=dijkstra(pp.f)+dijkstra(pp.s);
  return res;
}

bool comp(pdd a,pdd b){
  return (equals(a.f,b.f) ? b.s-a.s<-eps : b.f-a.f<-eps);
}

void solve(){
  make_graphs();
  pdd res(inf,inf);
  FOR(i,0,n-1){
    Segment s1(w[i],w[i+1]);
    FOR(j,0,m-1){
      Segment s2(e[j],e[j+1]);
      pdd tmp=check(s1,s2);
      if(comp(res,tmp))res=tmp;
    }
  }
  printf("%.10f %.10f\n",res.f,res.f+res.s);
}

int main()
{
  cin>>s.x>>s.y>>t.x>>t.y;
  cin>>n;
  w.resize(n);
  FOR(i,0,n)cin>>w[i].x>>w[i].y;
  cin>>m;
  e.resize(m);
  FOR(i,0,m)cin>>e[i].x>>e[i].y;
  solve();
  return 0;
}
accuracy: 0.47058823529411764
time_ms: 560
memory_kb: 3288
final_rank: 12