Problem:
ケーキ分割問題
English text is not available in this practice contest.
イコとピコはACM博士によって開発された人工知能を搭載した双子のロボットである．今日は二人の誕生日なので，博士は二人のためにたくさんのイチゴがのったケーキを用意した．
ケーキは横幅
W
×奥行き
H
の長方形の形をしている．
便宜上，ケーキは上から見たとき(0,0)，(
W
,0)，(
W
,
H
)，(0,
H
)を頂点とする長方形になるように置かれているとする．
また，二人に均等になるようにちょうど2
N
個のイチゴが乗っている．
せっかくなので，博士は二人にケーキを切らせることにした．
イコとピコは協力してケーキを切るため，イコが包丁の一端を辺(0,0)-(0,
H
)の間におき，ピコはもう一端を辺(
W
,0)-(
W
,
H
)の間において同時に下に下ろすという方法をとることにした．
もちろん包丁は直線状なので，選んだ2点を通る直線でケーキは2つに分かれる．(図E-1)
図E-1
博士は人工知能を完成させたことに満足し他の部分を適当に作ったために，二人の腕のパーツは不安定になってしまった．
そのため，辺(0,0)-(0,
H
)(または辺(
W
,0)-(
W
,
H
))上の狙った場所に置こうとしてもどうしてもずれてしまうのである．
二人はイチゴが好きなので，できれば
N
個ずつに分けたいと考えている．
そこで，
N
個ずつになるように切れない場合は2点を選びなおすことにした．
2
N
個のイチゴの配置によっては半分ずつに分けられなかったり，分けられたとしても，とても確率が低い場合も考えられる．
このような場合に何度も2点を選びなおすのは不毛なので，まず初めに
N
個ずつに分かれるように切れる確率を計算することにした．
二人の腕のパーツは不安定なので，動きを予想するのは難しい．
とりあえず，二人は「包丁を置く点は辺(0,0)-(0,
H
)(または辺(
W
,0)-(
W
,
H
))上に必ず乗り，置かれる確率はどの二点も等しい」という仮定を置くことにした．
また，イチゴの大きさを考慮するのも面倒なので，点とみなすことにした．
これは人工知能の性能を試すいい機会である．
博士と同じ研究所に勤めているあなたに，2
N
個のイチゴの位置を与えられたときに， 2人と同じ仮定を用いてイチゴが
N
個ずつに分かれる確率を計算するプログラムを作成する仕事が割り当てられた．
Input
入力は複数のデータセットからなる．入力の終わりは空白で区切られた3つのゼロからなる行によって与えられる．各データセットは1つのケーキに関する情報を表し，その形式は以下の通りである．
W
H
N
x
1
y
1
...
x
2N
y
2N
データセットの最初の行は3つの整数
W
,
H
,
N
からなり，それぞれケーキの横幅，奥行き，イチゴの個数/2を表す．
続く2
N
行は2個の整数からなり，それぞれイチゴのx座標とy座標を表す．
それぞれの値は次の制約を満たしている．
1 ≤
W
,
H
≤ 1,000
1 ≤
N
≤ 100
0 ≤
x
i
≤
W
0 ≤
y
i
≤
H
また，2つの異なるイチゴが同じ座標にあることはない．
Output
それぞれのデータセットに対して， 2人の仮定を用いた場合にイチゴが2等分される確率を表す実数を1行に出力せよ．
答えには 10
-8
を越える誤差があってはいけない．それ以外の余計な文字を出力してはならない．
Sample Input
2 2 1
0 1
2 1
3 3 1
1 1
2 1
0 0 0
Output for the Sample Input
0.5000000000
0.1666666667

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#define ll long long
#define endl '\n'
#define ls rt << 1
#define rs rt << 1 | 1
#define maxn 200010
using namespace std;

const double eps = 1e-12;
const double pi = acos(-1.0);
int sgn(double x)
{
    if (fabs(x) < eps)
        return 0;
    if (x < 0)
        return -1;
    else
        return 1;
}

ll n;
double w, h;
pair<double, double> a[maxn];
vector<double> check;
double ans[maxn];
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
#ifndef ONLINE_JUDGE
    //freopen("input.txt", "r", stdin);
    //freopen("standardout.txt", "w", stdout);
    ll _begin_time = clock();
#endif
    while (cin >> w >> h >> n && w + h + n)
    {
        for (int i = 0; i < n * 2; i++)
            cin >> a[i].first >> a[i].second;
        check.clear();
        check.push_back(0);
        check.push_back(h);
        a[n * 2] = {w, 0};
        a[n * 2 + 1] = {w, h};
        for (int i = 0; i < n * 2 + 2; i++)
            for (int j = i + 1; j < n * 2 + 2; j++)
                if (sgn(a[i].first - a[j].first))
                {
                    double tmp = a[i].second - a[i].first * (a[j].second - a[i].second) / (a[j].first - a[i].first);
                    if (tmp > 0 && tmp < h)
                        check.push_back(tmp);
                }
        for (int i = 0; i < n * 2; i++)
            if (!sgn(a[i].first))
            {
                if (a[i].second + eps * 2 < h)
                    check.push_back(a[i].second + eps * 2);
                if (a[i].second - eps * 2 > 0)
                    check.push_back(a[i].second - eps * 2);
            }
        sort(check.begin(), check.end());
        for (int i = 0; i < check.size(); i++)
        {
            vector<double> tmp;
            ll flag = 0;
            for (int j = 0; j < n * 2; j++)
            {
                if (!sgn(a[j].first))
                {
                    ll ptr = sgn(a[j].second - check[i]);
                    if (ptr == 1)
                        tmp.push_back(h);
                    else if (ptr == -1)
                        tmp.push_back(0);
                    else
                        flag = 1;
                }
                else
                {
                    double ptr = (a[j].second - check[i]) / a[j].first * w + check[i];
                    if (ptr > h)
                        ptr = h;
                    if (ptr < 0)
                        ptr = 0;
                    tmp.push_back(ptr);
                }
            }
            if (flag)
                ans[i] = 0;
            else
            {
                sort(tmp.begin(), tmp.end());
                ans[i] = tmp[n] - tmp[n - 1];
            }
        }
        double res = 0;
        for (int i = 0; i < check.size() - 1; i++)
            res += (check[i + 1] - check[i]) * (ans[i + 1] + ans[i]) / 2;
        cout << fixed << setprecision(10) << res / h / h << endl;
    }
#ifndef ONLINE_JUDGE
    ll _end_time = clock();
    //printf("time = %ld ms\n", _end_time - _begin_time);
#endif
    return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 3752
final_rank: 8

code_snippet: // (⁠◕⁠ᴗ⁠◕⁠✿⁠)

// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define srep(i, s, n) for (ll i = s; i < (n); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
template<typename T> using vc = vector<T>;
template<typename T> using vv = vc<vc<T>>;
template<typename T> using vvv = vv<vc<T>>;
using vi = vc<int>;using vvi = vv<int>; using vvvi = vv<vi>;
using ll = long long;using vl = vc<ll>;using vvl = vv<ll>; using vvvl = vv<vl>;
using ld = long double; using vld = vc<ld>; using vvld = vc<vld>; using vvvld = vc<vvld>;
using uint = unsigned int;
using ull = unsigned long long;
const ld pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
// const ll mod = 1000000007;
const ll mod = 998244353;
inline bool inside(ll y, ll x, ll H, ll W) {return 0 <= (y) and (y) < (H) and 0 <= (x) and (x) < (W); }

#define debug(var) do { cout << #var << " :\n"; view(var); } while(0)
template<typename T>void view(const T& e) {cout << e;}
template<typename T1, typename T2>void view(const pair<T1, T2>& p) {cout << "{" << p.first << ", " << p.second << "}";}
template<typename T>void view(const vc<T>& v) {for (const auto& e : v) {view(e);cout << " ";} cout << endl;}
template<typename T>void view(const vv<T>& vv) {for (const auto& v : vv) {view(v);cout << " ";} cout << endl;}
template<typename T>void view(const set<T>& s) {for (const auto& e : s) {view(e);cout << " ";} cout << endl;}
template<typename T>void view(const unordered_set<T>& s) {for (const auto& e : s) {view(e);cout << " ";} cout << endl;}
template<typename T1, typename T2>void view(const map<T1, T2>& mp){for (const auto& e : mp) {view(e);cout << " ";} cout << endl;}

int W, H, N;

void solve(){
    vi X(2 * N + 2), Y(2 * N + 2); rep(i, 2 * N) cin >> X[i] >> Y[i];
    X[2 * N] = W;
    Y[2 * N] = 0;
    X[2 * N + 1] = W;
    Y[2 * N + 1] = H;
    vc<ld> event;
    event.push_back(0);
    event.push_back(H);
    rep(j, 2 * N + 2) rep(i, j){
        if (X[i] != X[j]){
            ld p = -(Y[i] - Y[j]) * X[i] / (ld)(X[i] - X[j]) + Y[i];
            if (0 < p && p < H) event.push_back(p);
        }
    }
    sort(all(event));

    auto divide_point = [&](ld ny) -> pair<ld, ld>{
        vc<pair<ld, int>> A;
        rep(i, 2 * N) A.push_back({(Y[i] - ny) / (ld)(X[i]), i});
        sort(all(A));
        return {(Y[A[N - 1].second] - ny) * W / (ld)X[A[N - 1].second] + ny, (Y[A[N].second] - ny) * W / (ld)X[A[N].second] + ny};
    };
    ld ans = 0;
    rep(i, len(event) - 1){
        ld l0 = event[i], r0 = event[i + 1];
        auto [l1, r1] = divide_point((l0 + r0) / (ld)2);
        l1 = min((ld)H, max((ld)0, l1));
        r1 = min((ld)H, max((ld)0, r1));
        ans += (r1 - l1) * (r0 - l0);
    }
    ans /= ((ld)H * H);
    cout << fixed << setprecision(16) << ans << endl;
}

int main(){
    while (true){
        cin >> W >> H >> N;
        if (N == 0) break;
        solve();
    }
}
accuracy: 1
time_ms: 1760
memory_kb: 4072
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
const ll ILL=2167167167167167167;
const int INF=2100000000;
#define rep(i,a,b) for (int i=(int)(a);i<(int)(b);i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> int LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> int UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,T b){if(b<a){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,T b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
bool yneos(bool a,bool upp=false){if(a){cout<<(upp?"YES\n":"Yes\n");}else{cout<<(upp?"NO\n":"No\n");}return a;}
template<class T> void vec_out(vector<T> &p,int ty=0){
    if(ty==2){cout<<'{';for(int i=0;i<(int)p.size();i++){if(i){cout<<",";}cout<<'"'<<p[i]<<'"';}cout<<"}\n";}
    else{if(ty==1){cout<<p.size()<<"\n";}for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}}
template<class T> T vec_min(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmin(ans,x);return ans;}
template<class T> T vec_max(vector<T> &a){assert(!a.empty());T ans=a[0];for(auto &x:a) chmax(ans,x);return ans;}
template<class T> T vec_sum(vector<T> &a){T ans=T(0);for(auto &x:a) ans+=x;return ans;}
int pop_count(long long a){int res=0;while(a){res+=(a&1),a>>=1;}return res;}
template<class T> T square(T a){return a * a;}
// https://github.com/kth-competitive-programming/kactl/tree/main/content/geometry
template<class T> ll sgn(T x) { return (x > 0) - (x < 0); }
template<class T> struct Point {
    using P = Point;
    T x, y;
    explicit Point(T x = 0, T y = 0) : x(x), y(y) {}
    bool operator<(P p) const { return tie(x, y) < tie(p.x, p.y); }
    bool operator==(P p) const { return tie(x, y) == tie(p.x, p.y); }
    P operator+(P p) const { return P(x + p.x, y + p.y); }
    P operator-(P p) const { return P(x - p.x, y - p.y); }
    P operator*(T d) const { return P(x * d, y * d); }
    P operator/(T d) const { return P(x / d, y / d); }
    T dot(P p) const { return x * p.x + y * p.y; }
    T cross(P p) const { return x * p.y - y * p.x; }
    T cross(P a, P b) const { return (a - *this).cross(b - *this); }
    T dist2() const { return x * x + y * y; }
    long double dist() const { return sqrtl(dist2()); }
    // angle to x-axis in interval [-pi, pi]
    double angle() const { return atan2(y, x); }
    P unit() const { return *this / dist(); }  // makes dist()=1
    P perp() const { return P(-y, x); }        // rotates +90 degrees
    P normal() const { return perp().unit(); }
    // returns point rotated 'a' radians ccw around the origin
    P rotate(double a) const {
        return P(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a));
    }
    friend ostream& operator<<(ostream& os, P p) {
        return os << "(" << p.x << "," << p.y << ")";
    }
};

/* If a unique intersection point of the lines going through s1,e1 and s2,e2 exists \{1, point\} is returned.
If no intersection point exists \{0, (0,0)\} is returned and if infinitely many exists \{-1, (0,0)\} is returned.
The wrong position will be returned if P is Point<ll> and the intersection point does not have integer coordinates.
Products of three coordinates are used in intermediate steps so watch out for overflow if using ll or ll.
 * 	auto res = lineInter(s1,e1,s2,e2);
 * 	if (res.first == 1)
 * 		cout << "intersection point at " << res.second << endl; */

template<class P>
pair<ll, P> lineInter(P s1, P e1, P s2, P e2) {
    auto d = (e1 - s1).cross(e2 - s2);
    if(d == 0)  // if parallel
        return {-(s1.cross(e1, s2) == 0), P(0, 0)};
    auto p = s2.cross(e1, e2), q = s2.cross(e2, s1);
    return {1, (s1 * p + e1 * q) / d};
}

int W, H, N;


void solve();
// CITRUS CURIO CITY / FREDERIC
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    while (cin >> W >> H >> N, W) solve();
}

void solve(){
    using ld = long double;
    using P = Point<ld>;
    N *= 2;
    vector<P> pts(N);
    rep(i, 0, N) cin >> pts[i].x >> pts[i].y;
    set<ld> s;
    s.insert(0);
    s.insert(H);
    rep(i, 0, N) rep(j, 0, i){
        auto tmp = lineInter(pts[i], pts[j], P{0, 0}, P{0, (ld)H});
        if (tmp.first == 1 && 0 <= tmp.second.y && tmp.second.y <= H){
            s.insert(tmp.second.y);
        }
    }
    rep(i, 0, N){
        auto tmp = lineInter(pts[i], P{(ld)W, 0}, P{0, 0}, P{0, (ld)H});
        if (tmp.first == 1 && 0 <= tmp.second.y && tmp.second.y <= H){
            s.insert(tmp.second.y);
        }
        tmp = lineInter(pts[i], P{(ld)W, (ld)(H)}, P{0, 0}, P{0, (ld)H});
        if (tmp.first == 1 && 0 <= tmp.second.y && tmp.second.y <= H){
            s.insert(tmp.second.y);
        }
    }
    vector<ld> Y;
    for (auto x : s) Y.push_back(x);
    ld ans = 0;
    rep(i, 1, Y.size()){
        // cout << i << endl;
        vector<ld> ys;
        ld y = (Y[i - 1] + Y[i]) / 2;
        rep(j, 0, N){
            if (pts[j].x == 0){
                if (pts[j].y < y) ys.push_back(0);
                else ys.push_back(H);
                continue;
            }
            auto tmp = lineInter(pts[j], P{0, y}, P{(ld)W, 0}, P{(ld)W, (ld)H});
            assert(tmp.first == 1);
            ys.push_back(tmp.second.y);
        }
        // cout << ys.size() << endl;
        So(ys);
        ld diff = max((ld)(0), min((ld)(H), ys[N / 2]) - max((ld)0, ys[N / 2 - 1]));
        ans += diff * (Y[i] - Y[i - 1]);
    }
    ans /= H * H;
    cout << fixed << setprecision(20) << ans << "\n";
}
accuracy: 1
time_ms: 1170
memory_kb: 4348
final_rank: 16

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

using T = double;
const T eps = 1e-8;
using Point = complex<T>;
using Poly = vector<Point>;
#define X real()
#define Y imag()
template <typename T> inline bool eq(const T &a, const T &b) {
    return fabs(a - b) < eps;
}
bool cmp(const Point &a, const Point &b) {
    auto sub = [&](Point a) {
        return (a.Y < 0 ? -1 : (a.Y == 0 && a.X >= 0 ? 0 : 1));
    };
    if (sub(a) != sub(b))
        return sub(a) < sub(b);
    return a.Y * b.X < a.X * b.Y;
}
struct Line {
    Point a, b, dir;
    Line() {}
    Line(Point _a, Point _b) : a(_a), b(_b), dir(b - a) {}
    Line(T A, T B, T C) {
        if (eq(A, .0)) {
            a = Point(0, C / B), b = Point(1 / C / B);
        } else if (eq(B, .0)) {
            a = Point(C / A, 0), b = Point(C / A, 1);
        } else {
            a = Point(0, C / B), b = Point(C / A, 0);
        }
    }
};
struct Segment : Line {
    Segment() {}
    Segment(Point _a, Point _b) : Line(_a, _b) {}
};
struct Circle {
    Point p;
    T r;
    Circle() {}
    Circle(Point _p, T _r) : p(_p), r(_r) {}
};

istream &operator>>(istream &is, Point &p) {
    T x, y;
    is >> x >> y;
    p = Point(x, y);
    return is;
}
ostream &operator<<(ostream &os, Point &p) {
    os << fixed << setprecision(12) << p.X << ' ' << p.Y;
    return os;
}
Point unit(const Point &a) {
    return a / abs(a);
}
T dot(const Point &a, const Point &b) {
    return a.X * b.X + a.Y * b.Y;
}
T cross(const Point &a, const Point &b) {
    return a.X * b.Y - a.Y * b.X;
}
Point rot(const Point &a, const T &theta) {
    return Point(cos(theta) * a.X - sin(theta) * a.Y,
                 sin(theta) * a.X + cos(theta) * a.Y);
}
Point rot90(const Point &a) {
    return Point(-a.Y, a.X);
}
T arg(const Point &a, const Point &b, const Point &c) {
    double ret = acos(dot(a - b, c - b) / abs(a - b) / abs(c - b));
    if (cross(a - b, c - b) < 0)
        ret = -ret;
    return ret;
}

Point Projection(const Line &l, const Point &p) {
    T t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}
Point Projection(const Segment &l, const Point &p) {
    T t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}
Point Reflection(const Line &l, const Point &p) {
    return p + (Projection(l, p) - p) * 2.;
}
int ccw(const Point &a, Point b, Point c) {
    b -= a;
    c -= a;
    if (cross(b, c) > eps)
        return 1; // ccw

    if (cross(b, c) < -eps)
        return -1; // cw

    if (dot(b, c) < 0)
        return 2; // c,a,b

    if (norm(b) < norm(c))
        return -2; // a,b,c

    return 0;      // a,c,b

}
bool isOrthogonal(const Line &a, const Line &b) {
    return eq(dot(a.b - a.a, b.b - b.a), .0);
}
bool isParallel(const Line &a, const Line &b) {
    return eq(cross(a.b - a.a, b.b - b.a), .0);
}
bool isIntersect(const Segment &a, const Segment &b) {
    return ccw(a.a, a.b, b.a) * ccw(a.a, a.b, b.b) <= 0 and
           ccw(b.a, b.b, a.a) * ccw(b.a, b.b, a.b) <= 0;
}
int isIntersect(const Circle &a, const Circle &b) {
    T d = abs(a.p - b.p);
    if (d > a.r + b.r + eps)
        return 4;
    if (eq(d, a.r + b.r))
        return 3;
    if (eq(d, abs(a.r - b.r)))
        return 1;
    if (d < abs(a.r - b.r) - eps)
        return 0;
    return 2;
}
T Dist(const Line &a, const Point &b) {
    Point c = Projection(a, b);
    return abs(c - b);
}
T Dist(const Segment &a, const Point &b) {
    if (dot(a.b - a.a, b - a.a) < eps)
        return abs(b - a.a);
    if (dot(a.a - a.b, b - a.b) < eps)
        return abs(b - a.b);
    return abs(cross(a.b - a.a, b - a.a)) / abs(a.b - a.a);
}
T Dist(const Segment &a, const Segment &b) {
    if (isIntersect(a, b))
        return .0;
    T res = min({Dist(a, b.a), Dist(a, b.b), Dist(b, a.a), Dist(b, a.b)});
    return res;
}
Point Intersection(const Line &a, const Line &b) {
    T d1 = cross(a.b - a.a, b.b - b.a);
    T d2 = cross(a.b - a.a, a.b - b.a);
    if (eq(d1, 0.) and eq(d2, 0.))
        return b.a;
    return b.a + (b.b - b.a) * (d2 / d1);
}
Poly Intersection(const Circle &a, const Line &b) {
    Poly res;
    T d = Dist(b, a.p);
    if (d > a.r + eps)
        return res;
    Point h = Projection(b, a.p);
    if (eq(d, a.r)) {
        res.push_back(h);
        return res;
    }
    Point e = unit(b.b - b.a);
    T ph = sqrt(a.r * a.r - d * d);
    res.push_back(h - e * ph);
    res.push_back(h + e * ph);
    return res;
}
Poly Intersection(const Circle &a, const Segment &b) {
    Line c(b.a, b.b);
    Poly sub = Intersection(a, c);
    double xmi = min(b.a.X, b.b.X), xma = max(b.a.X, b.b.X);
    double ymi = min(b.a.Y, b.b.Y), yma = max(b.a.Y, b.b.Y);
    Poly res;
    rep(i, 0, sub.size()) {
        if (xmi <= sub[i].X + eps and sub[i].X - eps <= xma and
            ymi <= sub[i].Y + eps and sub[i].Y - eps <= yma) {
            res.push_back(sub[i]);
        }
    }
    return res;
}
Poly Intersection(const Circle &a, const Circle &b) {
    Poly res;
    int mode = isIntersect(a, b);
    T d = abs(a.p - b.p);
    if (mode == 4 or mode == 0)
        return res;
    if (mode == 3) {
        T t = a.r / (a.r + b.r);
        res.push_back(a.p + (b.p - a.p) * t);
        return res;
    }
    if (mode == 1) {
        if (b.r < a.r - eps) {
            res.push_back(a.p + (b.p - a.p) * (a.r / d));
        } else {
            res.push_back(b.p + (a.p - b.p) * (b.r / d));
        }
        return res;
    }
    T rc = (a.r * a.r + d * d - b.r * b.r) / d / 2.;
    T rs = sqrt(a.r * a.r - rc * rc);
    if (a.r - abs(rc) < eps)
        rs = 0;
    Point e = unit(b.p - a.p);
    res.push_back(a.p + rc * e + rs * e * Point(0, 1));
    res.push_back(a.p + rc * e + rs * e * Point(0, -1));
    return res;
}
Poly HalfplaneIntersection(vector<Line> &H) {
    sort(ALL(H), [&](Line &l1, Line &l2) { return cmp(l1.dir, l2.dir); });
    auto outside = [&](Line &L, Point p) -> bool {
        return cross(L.dir, p - L.a) < -eps;
    };
    deque<Line> deq;
    int sz = 0;
    rep(i, 0, SZ(H)) {
        while (sz > 1 and
               outside(H[i], Intersection(deq[sz - 1], deq[sz - 2]))) {
            deq.pop_back();
            sz--;
        }
        while (sz > 1 and outside(H[i], Intersection(deq[0], deq[1]))) {
            deq.pop_front();
            sz--;
        }
        if (sz > 0 and fabs(cross(H[i].dir, deq[sz - 1].dir)) < eps) {
            if (dot(H[i].dir, deq[sz - 1].dir) < 0) {
                return {};
            }
            if (outside(H[i], deq[sz - 1].a)) {
                deq.pop_back();
                sz--;
            } else
                continue;
        }
        deq.push_back(H[i]);
        sz++;
    }

    while (sz > 2 and outside(deq[0], Intersection(deq[sz - 1], deq[sz - 2]))) {
        deq.pop_back();
        sz--;
    }
    while (sz > 2 and outside(deq[sz - 1], Intersection(deq[0], deq[1]))) {
        deq.pop_front();
        sz--;
    }
    if (sz < 3)
        return {};
    deq.push_back(deq.front());
    Poly ret;
    rep(i, 0, sz) ret.push_back(Intersection(deq[i], deq[i + 1]));
    return ret;
}

T Area(const Poly &a) {
    T res = 0;
    int n = a.size();
    rep(i, 0, n) res += cross(a[i], a[(i + 1) % n]);
    return fabs(res / 2.);
}
T Area(const Poly &a, const Circle &b) {
    int n = a.size();
    if (n < 3)
        return .0;
    auto rec = [&](auto self, const Circle &c, const Point &p1,
                   const Point &p2) {
        Point va = c.p - p1, vb = c.p - p2;
        T f = cross(va, vb), res = .0;
        if (eq(f, .0))
            return res;
        if (max(abs(va), abs(vb)) < c.r + eps)
            return f;
        if (Dist(Segment(p1, p2), c.p) > c.r - eps)
            return c.r * c.r * arg(vb * conj(va));
        auto u = Intersection(c, Segment(p1, p2));
        Poly sub;
        sub.push_back(p1);
        for (auto &x : u)
            sub.push_back(x);
        sub.push_back(p2);
        rep(i, 0, sub.size() - 1) res += self(self, c, sub[i], sub[i + 1]);
        return res;
    };
    T res = .0;
    rep(i, 0, n) res += rec(rec, b, a[i], a[(i + 1) % n]);
    return fabs(res / 2.);
}
T Area(const Circle &a, const Circle &b) {
    T d = abs(a.p - b.p);
    if (d >= a.r + b.r - eps)
        return .0;
    if (d <= abs(a.r - b.r) + eps) {
        T r = min(a.r, b.r);
        return M_PI * r * r;
    }
    T ath = acos((a.r * a.r + d * d - b.r * b.r) / d / a.r / 2.);
    T res = a.r * a.r * (ath - sin(ath * 2) / 2.);
    T bth = acos((b.r * b.r + d * d - a.r * a.r) / d / b.r / 2.);
    res += b.r * b.r * (bth - sin(bth * 2) / 2.);
    return fabs(res);
}
bool isConvex(const Poly &a) {
    int n = a.size();
    int cur, pre, nxt;
    rep(i, 0, n) {
        pre = (i - 1 + n) % n;
        nxt = (i + 1) % n;
        cur = i;
        if (ccw(a[pre], a[cur], a[nxt]) == -1)
            return 0;
    }
    return 1;
}
int isContained(const Poly &a,
                const Point &b) { // 0:not contain,1:on edge,2:contain

    bool res = 0;
    int n = a.size();
    rep(i, 0, n) {
        Point p = a[i] - b, q = a[(i + 1) % n] - b;
        if (p.Y > q.Y)
            swap(p, q);
        if (p.Y < eps and eps < q.Y and cross(p, q) > eps)
            res ^= 1;
        if (eq(cross(p, q), .0) and dot(p, q) < eps)
            return 1;
    }
    return (res ? 2 : 0);
}
Poly ConvexHull(Poly &a) {
    sort(ALL(a), [](const Point &p, const Point &q) {
        return (eq(p.Y, q.Y) ? p.X < q.X : p.Y < q.Y);
    });
    a.erase(unique(ALL(a)), a.end());
    int n = a.size(), k = 0;
    Poly res(n * 2);
    for (int i = 0; i < n; res[k++] = a[i++]) {
        while (k >= 2 and
               cross(res[k - 1] - res[k - 2], a[i] - res[k - 1]) < eps)
            k--;
    }
    for (int i = n - 2, t = k + 1; i >= 0; res[k++] = a[i--]) {
        while (k >= t and
               cross(res[k - 1] - res[k - 2], a[i] - res[k - 1]) < eps)
            k--;
    }
    res.resize(k - 1);
    return res;
}
T Diam(const Poly &a) {
    int n = a.size();
    int x = 0, y = 0;
    rep(i, 1, n) {
        if (a[i].Y > a[x].Y)
            x = i;
        if (a[i].Y < a[y].Y)
            y = i;
    }
    T res = abs(a[x] - a[y]);
    int i = x, j = y;
    do {
        if (cross(a[(i + 1) % n] - a[i], a[(j + 1) % n] - a[j]) < 0)
            i = (i + 1) % n;
        else
            j = (j + 1) % n;
        chmax(res, abs(a[i] - a[j]));
    } while (i != x or j != y);
    return res;
}
Poly Cut(const Poly &a, const Line &l) {
    int n = a.size();
    Poly res;
    rep(i, 0, n) {
        Point p = a[i], q = a[(i + 1) % n];
        if (ccw(l.a, l.b, p) != -1)
            res.push_back(p);
        if (ccw(l.a, l.b, p) * ccw(l.a, l.b, q) < 0)
            res.push_back(Intersection(Line(p, q), l));
    }
    return res;
}

T Closest(Poly &a) {
    int n = a.size();
    if (n <= 1)
        return 0;
    sort(ALL(a), [&](Point a, Point b) {
        return (eq(a.X, b.X) ? a.Y < b.Y : a.X < b.X);
    });
    Poly buf(n);
    auto rec = [&](auto self, int lb, int rb) -> T {
        if (rb - lb <= 1)
            return (T)INF;
        int mid = (lb + rb) >> 1;
        auto x = a[mid].X;
        T res = min(self(self, lb, mid), self(self, mid, rb));
        inplace_merge(a.begin() + lb, a.begin() + mid, a.begin() + rb,
                      [&](auto p, auto q) { return p.Y < q.Y; });
        int ptr = 0;
        rep(i, lb, rb) {
            if (abs(a[i].X - x) >= res)
                continue;
            rep(j, 0, ptr) {
                auto sub = a[i] - buf[ptr - 1 - j];
                if (sub.Y >= res)
                    break;
                chmin(res, abs(sub));
            }
            buf[ptr++] = a[i];
        }
        return res;
    };
    return rec(rec, 0, n);
}

Circle Incircle(const Point &a, const Point &b, const Point &c) {
    T A = abs(b - c), B = abs(c - a), C = abs(a - b);
    Point p(A * a.X + B * b.X + C * c.X, A * a.Y + B * b.Y + C * c.Y);
    p /= (A + B + C);
    T r = Dist(Line(a, b), p);
    return Circle(p, r);
}
Circle Circumcircle(const Point &a, const Point &b, const Point &c) {
    Line l1((a + b) / 2., (a + b) / 2. + (b - a) * Point(0, 1));
    Line l2((b + c) / 2., (b + c) / 2. + (c - b) * Point(0, 1));
    Point p = Intersection(l1, l2);
    return Circle(p, abs(p - a));
}
Poly tangent(const Point &a, const Circle &b) {
    return Intersection(b, Circle(a, sqrt(norm(b.p - a) - b.r * b.r)));
}
vector<Line> tangent(const Circle &a, const Circle &b) {
    vector<Line> res;
    T d = abs(a.p - b.p);
    if (eq(d, 0.))
        return res;
    Point u = unit(b.p - a.p);
    Point v = u * Point(0, 1);
    for (int t : {-1, 1}) {
        T h = (a.r + b.r * t) / d;
        if (eq(h * h, 1.)) {
            res.push_back(Line(a.p + (h > 0 ? u : -u) * a.r,
                               a.p + (h > 0 ? u : -u) * a.r + v));
        } else if (1 > h * h) {
            Point U = u * h, V = v * sqrt(1 - h * h);
            res.push_back(Line(a.p + (U + V) * a.r, b.p - (U + V) * (b.r * t)));
            res.push_back(Line(a.p + (U - V) * a.r, b.p - (U - V) * (b.r * t)));
        }
    }
    return res;
}

/**
 * @brief Geometry
 */

int main() {
while(1) {
    double XS, YS;
    int N;
    cin >> XS >> YS >> N;
    if (N == 0) return 0;
    vector<Point> P(N*2);
    rep(i,0,N*2) {
        double x, y;
        cin >> x >> y;
        P[i] = Point(x,y);
    }
    auto Calc = [&](double D) -> double {
        Point Q(0.0,D);
        vector<double> E(N*2);
        rep(i,0,N*2) {
            if (P[i].real() == 0) {
                if (P[i].imag() <= D) E[i] = 0.0;
                else E[i] = YS;
            }
            else {
                Point R = Intersection(Line(Q,P[i]),Line(Point(XS,0.0),Point(XS,YS)));
                if (R.imag() < 0.0) E[i] = 0.0;
                else if (R.imag() > YS) E[i] = YS;
                else E[i] = R.imag();
            }
        }
        sort(ALL(E));
        return E[N]-E[N-1];
    };
    vector<double> Cand;
    Cand.push_back(0.0);
    Cand.push_back(YS);
    Line Jiku(Point(0.0,0.0),Point(0.0,YS));
    rep(i,0,N*2) {
        if (P[i].real() != XS) {
            Point Q = Intersection(Line(P[i],Point(XS,0.0)),Jiku);
            if (0 <= Q.imag() && Q.imag() <= YS) Cand.push_back(Q.imag());
            Q = Intersection(Line(P[i],Point(XS,YS)),Jiku);
            if (0 <= Q.imag() && Q.imag() <= YS) Cand.push_back(Q.imag());
        }
    }
    rep(i,0,N*2) {
        rep(j,i+1,N*2) {
            if (P[i].real() == P[j].real()) continue;
            Point Q = Intersection(Line(P[i],P[j]),Jiku);
            if (0 <= Q.imag() && Q.imag() <= YS) Cand.push_back(Q.imag()); 
        }
    }
    sort(ALL(Cand));
    double ANS = 0.0;
    rep(i,0,Cand.size()-1) {
        if (eq(Cand[i],Cand[i+1])) continue;
        ANS += (Cand[i+1]-Cand[i]) * Calc((Cand[i]+Cand[i+1])/2.0);
    }
    printf("%.12f\n",ANS/(YS*YS));
}
}
accuracy: 1
time_ms: 260
memory_kb: 3596
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vvvb = vector<vvb>;
#define all(A) A.begin(),A.end()
#define rep(i, n) for (int i = 0; i < (int) (n); i++)
template<class T>
void chmax(T& p, T q) { if (p < q)p = q; };

vector<double> X, Y;
double W, H;
ll N;
const double eps = 1e-12;
double cls(double x, double y, double X, double Y, double b = 0.0) {
    if (abs(x - X) < eps)return 1e18;
    double d = (Y - y) / (X - x) * (b - x) + y;
    return d;
}

double f(double y) {
    vector<pair<double, int>> P(2 * N);
    rep(i, 2*N)P[i] = {atan2(Y[i] - y,X[i]),i};
    sort(all(P));
    double D = cls(0.0, y, X[P[N - 1].second], Y[P[N - 1].second], W);
    D = min(max(D, 0.0), H);
    double U = cls(0.0, y, X[P[N].second], Y[P[N].second], W);
    U = min(max(U, 0.0), H);
    return abs(U - D);
}

void solve() {
    X.resize(2 * N);
    Y.resize(2 * N);
    rep(i, 2 * N)cin >> X[i] >> Y[i];
    vector<pair<double, double>> P;
    P.push_back({ 0,f(0.0) });
    P.push_back({ H,f(H) });
    rep(i, 2 * N) {
        double y = cls(X[i], Y[i], W, 0);
        if (0 <= y && y <= double(H))P.push_back({ y,f(y) });
        y = cls(X[i], Y[i], W, H);
        if (0 <= y && y <= double(H))P.push_back({ y,f(y) });
        rep(j, i) {
            y = cls(X[i], Y[i], X[j], Y[j]);
            if (0 <= y && y <= double(H))P.push_back({ y,f(y) });
        }
    }
    sort(all(P));
    double an = 0;
    double PN = P.size();
    cout << fixed << setprecision(15);
    rep(i, PN - 1) {
        an+= (P[i + 1].first - P[i].first) * f((P[i + 1].first + P[i].first) / 2.0);
        // an += (P[i + 1].first - P[i].first) * (P[i + 1].second + P[i].second) / 2.0;
    }

    cout << an/(H*H) << endl;


}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    while (cin >> W >> H >> N) {
        if (H == 0)return 0;
        solve();
    }

}
accuracy: 1
time_ms: 3190
memory_kb: 4200
final_rank: 18

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

template < class T > struct point {
    T x, y;
    point() : x(0), y(0) {}
    point(T x, T y) : x(x), y(y) {}
    point(std::pair< T, T > p) : x(p.first), y(p.second) {}
    point& operator+=(const point& p) { x += p.x, y += p.y; return *this; }
    point& operator-=(const point& p) { x -= p.x, y -= p.y; return *this; }
    point& operator*=(const T r) { x *= r, y *= r; return *this; }
    point& operator/=(const T r) { x /= r, y /= r; return *this; }
    point operator+(const point& p) const { return point(*this) += p; }
    point operator-(const point& p) const { return point(*this) -= p; }
    point operator*(const T r) const { return point(*this) *= r; }
    point operator/(const T r) const { return point(*this) /= r; }
    point operator-() const { return {-x, -y}; }
    bool operator==(const point& p) const { return x == p.x and y == p.y; }
    bool operator!=(const point& p) const { return x != p.x or  y != p.y; }
    bool operator<(const point& p) const { return x == p.x ? y < p.y : x < p.x; }
    point< T > rot(double theta) {
        static_assert(is_floating_point_v< T >);
        double cos_ = std::cos(theta), sin_ = std::sin(theta);
        return {cos_ * x - sin_ * y, sin_ * x + cos_ * y};
    }
};
template < class T > istream& operator>>(istream& is, point< T >& p) { return is >> p.x >> p.y; }
template < class T > ostream& operator<<(ostream& os, point< T >& p) { return os << p.x << " " << p.y; }
template < class T > T dot(const point< T >& a, const point< T >& b) { return a.x * b.x + a.y * b.y; }
template < class T > T det(const point< T >& a, const point< T >& b) { return a.x * b.y - a.y * b.x; }
template < class T > T norm(const point< T >& p) { return p.x * p.x + p.y * p.y; }
template < class T > double abs(const point< T >& p) { return std::sqrt(norm(p)); }
template < class T > double angle(const point< T >& p) { return std::atan2(p.y, p.x); }
template < class T > int sign(const T x) {
    T e = (is_integral_v< T > ? 1 : 1e-8);
    if(x <= -e) return -1;
    if(x >= +e) return +1;
    return 0;
}
template < class T > bool equals(const T& a, const T& b) { return sign(a - b) == 0; }
template < class T > int ccw(const point< T >& a, point< T > b, point< T > c) {
    b -= a, c -= a;
    if(sign(det(b, c)) == +1) return +1; // counter clockwise
    if(sign(det(b, c)) == -1) return -1; //         clockwise
    if(sign(dot(b, c)) == -1) return +2; // c-a-b
    if(norm(b) < norm(c)) return -2;     // a-b-c
    return 0;                            // a-c-b
}

template < class T > struct line {
    point< T > a, b;
    line() {}
    line(point< T > a, point< T > b) : a(a), b(b) {}
};
template < class T > point< T > projection(const line< T >& l, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    return l.a + (l.a - l.b) * dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
}
template < class T > point< T > reflection(const line< T >& l, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    return p + (projection(l, p) - p) * T(2);
}
template < class T > bool orthogonal(const line< T >& a, const line< T >& b) { return equals(dot(a.b - a.a, b.b - b.a), T(0)); }
template < class T > bool parallel  (const line< T >& a, const line< T >& b) { return equals(det(a.b - a.a, b.b - b.a), T(0)); }
template < class T > point< T > cross_point_ll(const line< T >& l, const line< T >& m) {
    static_assert(is_floating_point_v< T >);
    T A = det(l.b - l.a, m.b - m.a);
    T B = det(l.b - l.a, l.b - m.a);
    if(equals(abs(A), T(0)) and equals(abs(B), T(0))) return m.a;
    return m.a + (m.b - m.a) * B / A;
}

template < class T > using segment = line< T >;
template < class T > bool intersect_ss(const segment< T >& s, const segment< T >& t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 and ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}
template < class T > double distance_sp(const segment< T >& s, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    point r = projection(s, p);
    if(ccw(s.a, s.b, r) == 0) return abs(r - p);
    return std::min(abs(s.a - p), abs(s.b - p));
}
template < class T > double distance_ss(const segment< T >& a, const segment< T >& b) {
    if(intersect_ss(a, b)) return 0;
    return std::min({ distance_sp(a, b.a), distance_sp(a, b.b), distance_sp(b, a.a), distance_sp(b, a.b) });
}

template < class T > using polygon = std::vector< point< T > >;
template < class T > T area2(const polygon< T >& p) {
    T s = 0;
    int n = p.size();
    for(int i = 0; i < n; i++) s += det(p[i], p[(i + 1) % n]);
    return s;
}
template < class T > T area(const polygon< T >& p) { return area2(p) / T(2); }

template < class T > bool is_convex(const polygon< T >& p) {
    int n = p.size();
    for(int i = 0; i < n; i++) if(ccw(p[(i - 1 + n) % n], p[i], p[(i + 1) % n]) == -1) return false;
    return true;
}
template < class T > int contains(const polygon< T >& g, const point< T >& p) {
    int n = g.size();
    bool in = false;
    for(int i = 0; i < n; i++) {
        point a = g[i] - p, b = g[(i + 1) % n] - p;
        if(sign(a.y - b.y) == +1) std::swap(a, b);
        if(sign(a.y) <= 0 and sign(b.y) ==+1 and sign(det(a, b)) == -1) in = !in;
        if(sign(det(a, b)) == 0 and sign(dot(a, b)) <= 0) return 1; // ON
    }
    return in ? 2 : 0;
}
template < class T > polygon< T > convex_cut(const polygon< T >& p, const line< T >& l) {
    int n = p.size();
    polygon< T > res;
    for(int i = 0; i < n; i++) {
        point now = p[i], nxt = p[(i + 1) % n];
        if(ccw(l.a, l.b, now) != -1) res.push_back(now);
        if(ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) < 0) res.push_back(cross_point_ll(line(now, nxt), l));
    }
    return res;
}
template < class T > polygon< T > convex_hull(polygon< T >& p) {
    int n = p.size(), k = 0;
    if(n <= 2) return p;
    std::sort(p.begin(), p.end());
    polygon< T > ch(n + n);
    for(int i = 0; i < n; ch[k++] = p[i++])
        while(k >= 2 and sign(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) == -1) k--;
    for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--])
        while(k >= t and sign(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) == -1) k--;
    ch.resize(k - 1);
    return ch;
}
template < class T > T diameter2(const polygon< T >& p) {
    static_assert(is_floating_point_v< T >);
    int n = p.size(), is = 0, js = 0;
    for(int i = 1; i < n; i++) {
        if(sign(p[i].y - p[is].y) == +1) is = i;
        if(sign(p[i].y - p[js].y) == -1) js = i;
    }
    T dist_max = norm(p[is] - p[js]);
    int maxi = is, i = is, maxj = js, j = js;
    do {
        if(sign(det(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j])) >= 0) j = (j + 1) % n; else i = (i + 1) % n;
        if(norm(p[i] - p[j]) > dist_max) {
            dist_max = norm(p[i] - p[j]);
            maxi = i, maxj = j;
        }
    } while(i != is or j != js);
    return dist_max;
}
template < class T > double diameter(const polygon< T >& p) {
    static_assert(is_floating_point_v< T >);
    return std::sqrt(diameter2(p));
}

template < class T > struct circle {
    point< T > p;
    T r;
    circle() = default;
    circle(point< T > p, T r) : p(p), r(r) {}
};
template < class T > istream& operator>>(istream& is, circle< T >& c) { return is >> c.p >> c.r; }
template < class T > int intersect_cc(circle< T > c1, circle< T > c2) {
    if(c1.r < c2.r) std::swap(c1, c2);
    T d = abs(c1.p - c2.p);
    if(sign(c1.r + c2.r - d) == -1) return 4;
    if(equals(c1.r + c2.r, d)) return 3;
    if(sign(c1.r - c2.r - d) == -1) return 2;
    if(equals(c1.r - c2.r, d)) return 1;
    return 0;
}
template < class T > std::pair<point< T >, point< T >> cross_point_cc(const circle< T >& c1, const circle< T >& c2) {
    T d = abs(c1.p - c2.p);
    T a = std::acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    T t = angle(c2.p - c1.p);
    point< T > p1 = c1.p + point< T >(std::cos(t + a), std::sin(t + a)) * c1.r;
    point< T > p2 = c1.p + point< T >(std::cos(t - a), std::sin(t - a)) * c1.r;
    return {p1, p2};
}

f64 solve(int W, int H, int N) {
    vector<point<f64>> P(2 * N);
    for(int i : rep(2 * N)) P[i] = in();
    vector<point<f64>> Q = {
        point<f64>(0, 0), point<f64>(0, H), point<f64>(W, 0), point<f64>(W, H)
    };
    P.insert(P.end(), Q.begin(), Q.end());
    N = N + 2;

    vector<f64> ys = {0.0, f64(H)};
    auto div = [&](line<f64> l) {
        int L = 0, R = 0;
        for(int i : rep(2 * N)) {
            line<f64> m(P[i], P[i] + point<f64>(0, 1));
            f64 y = cross_point_ll<f64>(l, m).y;
            if(y + 1e-8 <= P[i].y) L++;
            if(y - 1e-8 <= P[i].y) R++;
        }
        return L <= N and N <= R;
    };
    auto push = [&](line<f64> l) {
        if(div(l)) {
            line<f64> m(point<f64>(0, 0), point<f64>(0, H));
            f64 y = cross_point_ll<f64>(l, m).y;
            if(0.0 <= y and y <= H) ys.push_back(y);
        }
    };
    for(int i : rep(2 * N)) {
        for(int j : rep(i + 1, 2 * N)) push(line<f64>(P[i], P[j]));
    }

    unique(ys);

    f64 ans = 0;
    const int n = ys.size();
    for(int k : rep(n - 1)) {
        f64 dL = ys[k + 1] - ys[k];
        f64 dR = [&] {
            f64 yL = (ys[k] + ys[k + 1]) / 2.0;
            f64 min = +1e18, max = -1e18;
            for(int i : rep(2 * N)) if(P[i].x > 0) {
                line<f64> l(P[i], point<f64>(0, yL));
                if(div(l)) {
                    f64 yR = cross_point_ll<f64>(l, line<f64>(point<f64>(W, 0), point<f64>(W, H))).y;
                    chmin(min, yR);
                    chmax(max, yR);
                }
            }
            chmax<f64>(min, 0.0);
            chmin<f64>(max, H);
            return std::max<f64>(0.0, max - min);
        }();
        ans += dL * dR;
    }
    return ans / f64(H * H);
}

int main() {
    while(true) {
        int W = in(), H = in(), N = in();
        if(make_tuple(W, H, N) == make_tuple(0, 0, 0)) return 0;
        printer::precision(20);
        print(solve(W, H, N));
    }
}
accuracy: 1
time_ms: 5590
memory_kb: 3632
final_rank: 17

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

template < class T > struct point {
    T x, y;
    point() : x(0), y(0) {}
    point(T x, T y) : x(x), y(y) {}
    point(std::pair< T, T > p) : x(p.first), y(p.second) {}
    point& operator+=(const point& p) { x += p.x, y += p.y; return *this; }
    point& operator-=(const point& p) { x -= p.x, y -= p.y; return *this; }
    point& operator*=(const T r) { x *= r, y *= r; return *this; }
    point& operator/=(const T r) { x /= r, y /= r; return *this; }
    point operator+(const point& p) const { return point(*this) += p; }
    point operator-(const point& p) const { return point(*this) -= p; }
    point operator*(const T r) const { return point(*this) *= r; }
    point operator/(const T r) const { return point(*this) /= r; }
    point operator-() const { return {-x, -y}; }
    bool operator==(const point& p) const { return x == p.x and y == p.y; }
    bool operator!=(const point& p) const { return x != p.x or  y != p.y; }
    bool operator<(const point& p) const { return x == p.x ? y < p.y : x < p.x; }
    point< T > rot(double theta) {
        static_assert(is_floating_point_v< T >);
        double cos_ = std::cos(theta), sin_ = std::sin(theta);
        return {cos_ * x - sin_ * y, sin_ * x + cos_ * y};
    }
};
template < class T > istream& operator>>(istream& is, point< T >& p) { return is >> p.x >> p.y; }
template < class T > ostream& operator<<(ostream& os, point< T >& p) { return os << p.x << " " << p.y; }
template < class T > T dot(const point< T >& a, const point< T >& b) { return a.x * b.x + a.y * b.y; }
template < class T > T det(const point< T >& a, const point< T >& b) { return a.x * b.y - a.y * b.x; }
template < class T > T norm(const point< T >& p) { return p.x * p.x + p.y * p.y; }
template < class T > double abs(const point< T >& p) { return std::sqrt(norm(p)); }
template < class T > double angle(const point< T >& p) { return std::atan2(p.y, p.x); }
template < class T > int sign(const T x) {
    T e = (is_integral_v< T > ? 1 : 1e-8);
    if(x <= -e) return -1;
    if(x >= +e) return +1;
    return 0;
}
template < class T > bool equals(const T& a, const T& b) { return sign(a - b) == 0; }
template < class T > int ccw(const point< T >& a, point< T > b, point< T > c) {
    b -= a, c -= a;
    if(sign(det(b, c)) == +1) return +1; // counter clockwise
    if(sign(det(b, c)) == -1) return -1; //         clockwise
    if(sign(dot(b, c)) == -1) return +2; // c-a-b
    if(norm(b) < norm(c)) return -2;     // a-b-c
    return 0;                            // a-c-b
}

template < class T > struct line {
    point< T > a, b;
    line() {}
    line(point< T > a, point< T > b) : a(a), b(b) {}
};
template < class T > point< T > projection(const line< T >& l, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    return l.a + (l.a - l.b) * dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
}
template < class T > point< T > reflection(const line< T >& l, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    return p + (projection(l, p) - p) * T(2);
}
template < class T > bool orthogonal(const line< T >& a, const line< T >& b) { return equals(dot(a.b - a.a, b.b - b.a), T(0)); }
template < class T > bool parallel  (const line< T >& a, const line< T >& b) { return equals(det(a.b - a.a, b.b - b.a), T(0)); }
template < class T > point< T > cross_point_ll(const line< T >& l, const line< T >& m) {
    static_assert(is_floating_point_v< T >);
    T A = det(l.b - l.a, m.b - m.a);
    T B = det(l.b - l.a, l.b - m.a);
    if(equals(abs(A), T(0)) and equals(abs(B), T(0))) return m.a;
    return m.a + (m.b - m.a) * B / A;
}

template < class T > using segment = line< T >;
template < class T > bool intersect_ss(const segment< T >& s, const segment< T >& t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 and ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}
template < class T > double distance_sp(const segment< T >& s, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    point r = projection(s, p);
    if(ccw(s.a, s.b, r) == 0) return abs(r - p);
    return std::min(abs(s.a - p), abs(s.b - p));
}
template < class T > double distance_ss(const segment< T >& a, const segment< T >& b) {
    if(intersect_ss(a, b)) return 0;
    return std::min({ distance_sp(a, b.a), distance_sp(a, b.b), distance_sp(b, a.a), distance_sp(b, a.b) });
}

template < class T > using polygon = std::vector< point< T > >;
template < class T > T area2(const polygon< T >& p) {
    T s = 0;
    int n = p.size();
    for(int i = 0; i < n; i++) s += det(p[i], p[(i + 1) % n]);
    return s;
}
template < class T > T area(const polygon< T >& p) { return area2(p) / T(2); }

template < class T > bool is_convex(const polygon< T >& p) {
    int n = p.size();
    for(int i = 0; i < n; i++) if(ccw(p[(i - 1 + n) % n], p[i], p[(i + 1) % n]) == -1) return false;
    return true;
}
template < class T > int contains(const polygon< T >& g, const point< T >& p) {
    int n = g.size();
    bool in = false;
    for(int i = 0; i < n; i++) {
        point a = g[i] - p, b = g[(i + 1) % n] - p;
        if(sign(a.y - b.y) == +1) std::swap(a, b);
        if(sign(a.y) <= 0 and sign(b.y) ==+1 and sign(det(a, b)) == -1) in = !in;
        if(sign(det(a, b)) == 0 and sign(dot(a, b)) <= 0) return 1; // ON
    }
    return in ? 2 : 0;
}
template < class T > polygon< T > convex_cut(const polygon< T >& p, const line< T >& l) {
    int n = p.size();
    polygon< T > res;
    for(int i = 0; i < n; i++) {
        point now = p[i], nxt = p[(i + 1) % n];
        if(ccw(l.a, l.b, now) != -1) res.push_back(now);
        if(ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) < 0) res.push_back(cross_point_ll(line(now, nxt), l));
    }
    return res;
}
template < class T > polygon< T > convex_hull(polygon< T >& p) {
    int n = p.size(), k = 0;
    if(n <= 2) return p;
    std::sort(p.begin(), p.end());
    polygon< T > ch(n + n);
    for(int i = 0; i < n; ch[k++] = p[i++])
        while(k >= 2 and sign(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) == -1) k--;
    for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--])
        while(k >= t and sign(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) == -1) k--;
    ch.resize(k - 1);
    return ch;
}
template < class T > T diameter2(const polygon< T >& p) {
    static_assert(is_floating_point_v< T >);
    int n = p.size(), is = 0, js = 0;
    for(int i = 1; i < n; i++) {
        if(sign(p[i].y - p[is].y) == +1) is = i;
        if(sign(p[i].y - p[js].y) == -1) js = i;
    }
    T dist_max = norm(p[is] - p[js]);
    int maxi = is, i = is, maxj = js, j = js;
    do {
        if(sign(det(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j])) >= 0) j = (j + 1) % n; else i = (i + 1) % n;
        if(norm(p[i] - p[j]) > dist_max) {
            dist_max = norm(p[i] - p[j]);
            maxi = i, maxj = j;
        }
    } while(i != is or j != js);
    return dist_max;
}
template < class T > double diameter(const polygon< T >& p) {
    static_assert(is_floating_point_v< T >);
    return std::sqrt(diameter2(p));
}

template < class T > struct circle {
    point< T > p;
    T r;
    circle() = default;
    circle(point< T > p, T r) : p(p), r(r) {}
};
template < class T > istream& operator>>(istream& is, circle< T >& c) { return is >> c.p >> c.r; }
template < class T > int intersect_cc(circle< T > c1, circle< T > c2) {
    if(c1.r < c2.r) std::swap(c1, c2);
    T d = abs(c1.p - c2.p);
    if(sign(c1.r + c2.r - d) == -1) return 4;
    if(equals(c1.r + c2.r, d)) return 3;
    if(sign(c1.r - c2.r - d) == -1) return 2;
    if(equals(c1.r - c2.r, d)) return 1;
    return 0;
}
template < class T > std::pair<point< T >, point< T >> cross_point_cc(const circle< T >& c1, const circle< T >& c2) {
    T d = abs(c1.p - c2.p);
    T a = std::acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    T t = angle(c2.p - c1.p);
    point< T > p1 = c1.p + point< T >(std::cos(t + a), std::sin(t + a)) * c1.r;
    point< T > p2 = c1.p + point< T >(std::cos(t - a), std::sin(t - a)) * c1.r;
    return {p1, p2};
}

f64 solve(int W, int H, int N) {
    vector<point<f64>> P(2 * N);
    for(int i : rep(2 * N)) P[i] = in();
    vector<point<f64>> Q = {
        point<f64>(0, 0), point<f64>(0, H), point<f64>(W, 0), point<f64>(W, H)
    };
    const int M = 4;

    vector<f64> ys = {0.0, f64(H)};

    auto div = [&](line<f64> l) {
        int L = 0, R = 0;
        for(int i : rep(2 * N)) {
            line<f64> m(P[i], P[i] + point<f64>(0, 1));
            f64 y = cross_point_ll<f64>(l, m).y;
            if(y + 1e-8 <= P[i].y) L++;
            if(y - 1e-8 <= P[i].y) R++;
        }
        return L <= N and N <= R;
    };

    auto push = [&](line<f64> l) {
        if(div(l)) {
            line<f64> m(point<f64>(0, 0), point<f64>(0, H));
            f64 y = cross_point_ll<f64>(l, m).y;
            if(0.0 <= y and y <= H) ys.push_back(y);
        }
    };

    for(int i : rep(2 * N)) for(int j : rep(i + 1, 2 * N)) push(line<f64>(P[i], P[j]));
    for(int i : rep(2 * N)) for(int j : rep(       M)) push(line<f64>(P[i], Q[j]));
    for(int i : rep(    M)) for(int j : rep(i + 1, M)) push(line<f64>(Q[i], Q[j]));

    unique(ys);

    f64 ans = 0;
    const int n = ys.size();
    for(int k : rep(n - 1)) {
        f64 dL = ys[k + 1] - ys[k];
        f64 dR = [&] {
            f64 yL = (ys[k] + ys[k + 1]) / 2.0;
            f64 min = +1e18, max = -1e18;
            for(int i : rep(2 * N)) if(P[i].x > 0) {
                line<f64> l(P[i], point<f64>(0, yL));
                if(div(l)) {
                    f64 yR = cross_point_ll<f64>(l, line<f64>(point<f64>(W, 0), point<f64>(W, H))).y;
                    chmin(min, yR);
                    chmax(max, yR);
                }
            }
            for(int i : rep(M)) if(Q[i].x > 0) {
                line<f64> l(Q[i], point<f64>(0, yL));
                if(div(l)) {
                    f64 yR = cross_point_ll<f64>(l, line<f64>(point<f64>(W, 0), point<f64>(W, H))).y;
                    chmin(min, yR);
                    chmax(max, yR);
                }
            }
            chmax<f64>(min, 0.0);
            chmin<f64>(max, H);
            return std::max<f64>(0.0, max - min);
        }();
        ans += dL * dR;
    }
    return ans / f64(H * H);
}

int main() {
    while(true) {
        int W = in(), H = in(), N = in();
        if(make_tuple(W, H, N) == make_tuple(0, 0, 0)) return 0;
        printer::precision(20);
        print(solve(W, H, N));
    }
}
accuracy: 1
time_ms: 5380
memory_kb: 3528
final_rank: 15

code_snippet: // time complexity: O(N^3 log N)

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

double subsolve(int N, const vector<double>& X, const vector<double>& Y) {
	vector<double> slopes = { 0.0, 1.0 };
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (X[i] < X[j]) {
				double r = (Y[j] - Y[i]) / (X[j] - X[i]);
				if (0 < r && r < 1) {
					slopes.push_back(r);
				}
			}
		}
	}
	sort(slopes.begin(), slopes.end());
	double ans = 0.0;
	for (int i = 0; i < int(slopes.size()) - 1; i++) {
		double sl = slopes[i];
		double sr = slopes[i + 1];
		double sm = (sl + sr) / 2;
		vector<int> perm(N);
		for (int j = 0; j < N; j++) {
			perm[j] = j;
		}
		sort(perm.begin(), perm.end(), [&](int va, int vb) {
			return Y[va] - sm * X[va] < Y[vb] - sm * X[vb];
		});
		auto calc = [&](int pos) -> double {
			double x = X[pos];
			double y = Y[pos];
			vector<double> borders = { sl, sr };
			if (x != 0.0 && sl < y / x && y / x < sr) {
				borders.push_back(y / x);
			}
			if (x != 1.0 && sl < (1.0 - y) / (1.0 - x) && (1.0 - y) / (1.0 - x) < sr) {
				borders.push_back((1.0 - y) / (1.0 - x));
			}
			sort(borders.begin(), borders.end());
			int m = borders.size();
			vector<double> w(m);
			for (int i = 0; i < m; i++) {
				double s = borders[i];
				w[i] = min(max(y - s * x, 0.0), 1.0 - s);
			}
			double res = 0.0;
			for (int i = 0; i < m - 1; i++) {
				res += (w[i] + w[i + 1]) * (borders[i + 1] - borders[i]) / 2.0;
			}
			return res;
		};
		// cerr << "! " << sl << ' ' << sr << ' ' << calc(perm[N / 2]) << ' ' << calc(perm[N / 2 - 1]) << endl;
		ans += calc(perm[N / 2]) - calc(perm[N / 2 - 1]);
	}
	return ans;
}

int main() {
	while (true) {
		int W, H, N;
		cin >> W >> H >> N;
		if (W == 0 && H == 0 && N == 0) {
			break;
		}
		N *= 2;
		vector<double> X(N), Y(N);
		for (int i = 0; i < N; i++) {
			cin >> X[i] >> Y[i];
			X[i] /= W;
			Y[i] /= H;
		}
		double ans1 = subsolve(N, X, Y);
		for (int i = 0; i < N; i++) {
			Y[i] = 1.0 - Y[i];
		}
		double ans2 = subsolve(N, X, Y);
		cout.precision(15);
		cout << fixed << ans1 + ans2 << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 560
memory_kb: 3596
final_rank: 5

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

using i64 = long long;

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);

    cout << fixed << setprecision(12);

    int W, H, n;
    
    auto solve = [&]() {
        n *= 2;

        vector<int> x(n), y(n);
        for (int i = 0; i < n; i++) {
            cin >> x[i] >> y[i];
        }
        x.push_back(W), y.push_back(0);
        x.push_back(W), y.push_back(H);

        vector<double> ys;

        for (int i = 0; i < n + 2; i++) {
            for (int j = i + 1; j < n + 2; j++) {
                if (x[i] == x[j]) {
                    continue;
                }
                double p = 1.0 * (x[i] * y[j] - x[j] * y[i]) / (x[i] - x[j]);
                if (0 < p && p < H) {
                    ys.push_back(p);
                }
            }
        }

        ys.push_back(0);
        ys.push_back(H);
        sort(ys.begin(), ys.end());

        double ans = 0;

        for (int i = 0; i < int(ys.size()) - 1; i++) {
            double yl = ys[i], yr = ys[i + 1];
            double ym = (yl + yr) / 2;

            vector<double> s(n);
            for (int j = 0; j < n; j++) {
                if (x[j] == 0) {
                    s[j] = y[j] < ym ? -1e9 : 1e9;    
                } else {
                    s[j] = (y[j] - ym) / x[j];
                }
            }

            sort(s.begin(), s.end());

            double l = clamp<double>(W * s[n / 2 - 1] + ym, 0, H);
            double r = clamp<double>(W * s[n / 2] + ym, 0, H);

            ans += (r - l) * (yr - yl);
        }

        ans /= H * H;

        cout << ans << '\n';
    };

    while (cin >> W >> H >> n && n != 0) {
        solve();
    }

    return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 3692
final_rank: 6

code_snippet: //#define _GLIBCXX_DEBUG

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

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define UNIQUE(a) (a).erase(unique((a).begin(),(a).end()),(a).end())
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T> using PQ = priority_queue<T>;
template<typename T> using QP = priority_queue<T,vector<T>,greater<T>>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}  
template<typename T1,typename T2,typename T3>void anss(T1 x,T2 y,T3 z){ans(x!=y,x,z);};  
template<typename T>void debug(const T &v,ll h,ll w,string sv=" "){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout<<sv<<v[i][j];cout<<endl;}};
template<typename T>void debug(const T &v,ll n,string sv=" "){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout<<sv<<v[i];cout<<endl;};
template<typename T>void debug(const vector<T>&v){debug(v,v.size());}
template<typename T>void debug(const vector<vector<T>>&v){for(auto &vv:v)debug(vv,vv.size());}
template<typename T>void debug(stack<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(queue<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(deque<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop_front();}cout<<endl;}
template<typename T>void debug(PQ<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(QP<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(const set<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T>void debug(const multiset<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T,size_t size>void debug(const array<T, size> &a){for(auto z:a)cout<<z<<" ";cout<<endl;}
template<typename T,typename V>void debug(const map<T,V>&v){for(auto z:v)cout<<"["<<z.first<<"]="<<z.second<<",";cout<<endl;}
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
//vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
template<typename T>void rearrange(vector<int>&ord, vector<T>&v){
  auto tmp = v;
  for(int i=0;i<tmp.size();i++)v[i] = tmp[ord[i]];
}
template<typename Head, typename... Tail>void rearrange(vector<int>&ord,Head&& head, Tail&&... tail){
  rearrange(ord, head);
  rearrange(ord, tail...);
}
template<typename T> vector<int> ascend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]<v[j];});
  return ord;
}
template<typename T> vector<int> descend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]>v[j];});
  return ord;
}
template<typename T> vector<T> inv_perm(const vector<T>&ord){
  vector<T>inv(ord.size());
  for(int i=0;i<ord.size();i++)inv[ord[i]] = i;
  return inv;
}
ll FLOOR(ll n,ll div){assert(div>0);return n>=0?n/div:(n-div+1)/div;}
ll CEIL(ll n,ll div){assert(div>0);return n>=0?(n+div-1)/div:n/div;}
ll digitsum(ll n){ll ret=0;while(n){ret+=n%10;n/=10;}return ret;}
ll modulo(ll n,ll d){return (n%d+d)%d;};
template<typename T>T min(const vector<T>&v){return *min_element(v.begin(),v.end());}
template<typename T>T max(const vector<T>&v){return *max_element(v.begin(),v.end());}
template<typename T>T acc(const vector<T>&v){return accumulate(v.begin(),v.end(),T(0));};
template<typename T>T reverse(const T &v){return T(v.rbegin(),v.rend());};
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int popcount(ll x){return __builtin_popcountll(x);};
int poplow(ll x){return __builtin_ctzll(x);};
int pophigh(ll x){return 63 - __builtin_clzll(x);};
template<typename T>T poll(queue<T> &q){auto ret=q.front();q.pop();return ret;};
template<typename T>T poll(priority_queue<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(QP<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(stack<T> &s){auto ret=s.top();s.pop();return ret;};
ll MULT(ll x,ll y){if(LLONG_MAX/x<=y)return LLONG_MAX;return x*y;}
ll POW2(ll x, ll k){ll ret=1,mul=x;while(k){if(mul==LLONG_MAX)return LLONG_MAX;if(k&1)ret=MULT(ret,mul);mul=MULT(mul,mul);k>>=1;}return ret;}
ll POW(ll x, ll k){ll ret=1;for(int i=0;i<k;i++){if(LLONG_MAX/x<=ret)return LLONG_MAX;ret*=x;}return ret;}
template< typename T = int >
struct edge {
  int to;
  T cost;
  int id;
  edge():id(-1){};
  edge(int to, T cost = 1, int id = -1):to(to), cost(cost), id(id){}
  operator int() const { return to; }
};

template<typename T>
using Graph = vector<vector<edge<T>>>;
template<typename T>
Graph<T>revgraph(const Graph<T> &g){
  Graph<T>ret(g.size());
  for(int i=0;i<g.size();i++){
    for(auto e:g[i]){
      int to = e.to;
      e.to = i;
      ret[to].push_back(e);
    }
  }
  return ret;
}
template<typename T>
Graph<T> readGraph(int n,int m,int indexed=1,bool directed=false,bool weighted=false){
  Graph<T> ret(n);
  for(int es = 0; es < m; es++){
    int u,v;
    T w=1;
    cin>>u>>v;u-=indexed,v-=indexed;
    if(weighted)cin>>w;
    ret[u].emplace_back(v,w,es);
    if(!directed)ret[v].emplace_back(u,w,es);
  }
  return ret;
}
template<typename T>
Graph<T> readParent(int n,int indexed=1,bool directed=true){
  Graph<T>ret(n);
  for(int i=1;i<n;i++){
    int p;cin>>p;
    p-=indexed;
    ret[p].emplace_back(i);
    if(!directed)ret[i].emplace_back(p);
  }
  return ret;
}

template <typename F>
class
#if defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
  [[nodiscard]]
#endif  // defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
FixPoint final : private F
{
public:
  template <typename G>
  explicit constexpr FixPoint(G&& g) noexcept
    : F{std::forward<G>(g)}
    {}

  template <typename... Args>
  constexpr decltype(auto)
  operator()(Args&&... args) const
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9
  noexcept(noexcept(F::operator()(std::declval<FixPoint>(), std::declval<Args>()...)))
#endif  // !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9
  {
    return F::operator()(*this, std::forward<Args>(args)...);
  }
};  // class FixPoint


#if defined(__cpp_deduction_guides)
template <typename F>
FixPoint(F&&)
  -> FixPoint<std::decay_t<F>>;
#endif  // defined(__cpp_deduction_guides)


namespace
{
  template <typename F>
#if !defined(__has_cpp_attribute) || !__has_cpp_attribute(nodiscard)
#  if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4)
  __attribute__((warn_unused_result))
#  elif defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_Check_return_)
  _Check_return_
#  endif  // defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#endif  // !defined(__has_cpp_attribute) || !__has_cpp_attribute(nodiscard)
  inline constexpr decltype(auto)
  makeFixPoint(F&& f) noexcept
{
  return FixPoint<std::decay_t<F>>{std::forward<std::decay_t<F>>(f)};
}
}  // namespace

using Real = long double;
using Point = complex<Real>;
const Real EPS = 1e-10, PI = acos((Real)(-1.0));

inline bool eq(Real a, Real b) { return fabs(b - a) < EPS; }
inline bool eq(Point a, Point b) { return fabs(b - a) < EPS; }

Point operator*(const Point &p, const Real &d) {
  return Point(real(p) * d, imag(p) * d);
}

istream &operator>>(istream &is, Point &p) {
  Real a, b;
  is >> a >> b;
  p = Point(a, b);
  return is;
}

ostream &operator<<(ostream &os, Point &p) {
  return os << fixed << setprecision(10) << p.real() << " " << p.imag();
}

Point rotate(Real theta, const Point &p) {
  return Point(cos(theta) * p.real() - sin(theta) * p.imag(), sin(theta) * p.real() + cos(theta) * p.imag());
}

namespace std {
  bool operator<(const Point& a, const Point& b) {
    return !eq(a.real(), b.real()) ? a.real() < b.real() : a.imag() < b.imag();
  }
}

struct Line {
  Point a, b;
  Line() = default;
  Line(Point a, Point b): a(a), b(b) {}

  friend ostream &operator<<(ostream &os, Line &p) {
    return os << p.a << " to " << p.b;
  }

  friend istream &operator>>(istream &is, Line &a) {
    return is >> a.a >> a.b;
  }
};

struct Circle {
  Point c;
  Real r;
  Circle() = default;
  Circle(Point c, Real r): c(c), r(r) {}

  friend ostream &operator<<(ostream &os, Circle &c) {
    return os << c.c << ": " << c.r;
  }

  friend istream &operator>>(istream &is, Circle &c) {
    return is >> c.c >> c.r;
  }
};

Real cross(const Point &a, const Point &b) {
  return real(a) * imag(b) - real(b) * imag(a);
}

Real dot(const Point &a, const Point &b) {
  return real(a) * real(b) + imag(a) * imag(b);
}

struct Segment : Line {
  Segment() = default;
  Segment(Point a, Point b) : Line(a, b) {}
};

int ccw(const Point &a, Point b, Point c) {
  b = b - a, c = c - a;
  if (cross(b, c) > EPS) return +1; // COUNTER_CLOCKWISE
  if (cross(b, c) < -EPS) return -1; // CLOCKWISE
  if (dot(b, c) < 0) return +2; // ONLINE_BACK
  if (norm(b) < norm(c)) return -2; // ONLINE_FRONT
  return 0; // ON_SEGMENT
}

bool intersect(const Segment &s, const Point &p) {
  return ccw(s.a, s.b, p) == 0;
}

bool intersect(const Segment &s, const Segment&t) {
  return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

bool intersect(const Line &l, const Segment& s) {
  return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < EPS;
}

int intersect(const Circle &c, const Circle &d) {
  Real dis = fabs(c.c - d.c);

  if (dis > c.r + d.r + EPS) return 4;
  else if (eq(dis, c.r + d.r)) return 3;
  else if (eq(dis, abs(c.r - d.r))) return 1;
  else if (dis + min(c.r, d.r) < max(c.r, d.r) - EPS) return 0;
  else return 2;
}

bool parallel(const Line &a, const Line &b) {
  return abs(cross(a.b - a.a, b.b - b.a)) < EPS;
}

bool orthogonal(const Line &a, const Line &b) {
  return abs(dot(a.b - a.a, b.b - b.a)) < EPS;
}

Point projection(const Line& s, const Point &p) {
  double t = dot(p - s.a, s.b - s.a) / norm(s.b - s. a);
  return s.a + (s.b - s.a) * t;
}

Point projection(const Segment& l, const Point &p) {
  return projection(Line(l), p);
}

Point reflection(const Line &l, const Point &p) {
  Point r = projection(l, p);
  return p + (r - p) * 2;
}

Real distance(const Line &l, const Point &p) {
  Point r = projection(l, p);
  return fabs(p - r);
}

Real distance(const Segment&s, const Point &p) {
  Point r = projection(s, p);
  if (intersect(s, r)) return abs(r - p);
  return min(abs(s.a - p), abs(s.b - p));
}

Real distance(const Segment& a, const Segment& b) {
  if (intersect(a, b)) return 0;
  return min({
    distance(a, b.a),
    distance(a, b.b),
    distance(b, a.a),
    distance(b, a.b)
  });
}

Point crosspoint(const Line &l, const Line &m) {
  Real A = cross(l.b - l.a, m.b - m.a);
  Real B = cross(l.b - l.a, l.b - m.a);
  if (eq(abs(A), 0.0) && eq(abs(B), 0.0)) return m.a;
  return m.a + (m.b - m.a) * B / A;
}

Point crosspoint(const Segment& l, const Segment& m) {
  return crosspoint(Line(l), Line(m));
}

Line bisector_of_angle(const Point& a, const Point& b, const Point& c) {
  Real d_ab = fabs(a - b);
  Real d_bc = fabs(b - c);
  Point c_ = b + (c - b) * d_ab / d_bc;

  return Line(b, (a + c_) * 0.5);
}

Line bisector(const Point& a, const Point& b) {
  Point c = (a + b) * 0.5;
  Point d = c + rotate(PI / 2, b - c);

  return Line(c, d);
}

int intersect(const Circle &c, const Line &l) {
  Real d = distance(l, c.c);

  if (d > c.r + EPS) return 0;
  if (eq(d, c.r)) return 1;
  return 2;
}

pair<Point, Point> crosspoint(const Circle& c, const Line& l) {
  Real d = distance(l, c.c);

  Point p = projection(l, c.c);
  if (intersect(c, l) == 1) return { p, p };

  Real d2 = sqrt(c.r * c.r - d * d);
  Point v = (l.a - l.b) * (1.0 / fabs(l.a - l.b));

  return { p + d2 * v, p - d2 * v };
}

pair<Point, Point> crosspoint(const Circle &c1, const Circle &c2) {
  Real d = fabs(c1.c - c2.c);
  Real x1 = (c1.r * c1.r + d * d - c2.r * c2.r) / 2 / d;
  Real y = sqrt(c1.r * c1.r - x1 * x1);

  Point base = (c2.c * x1 + c1.c * (d - x1)) * (1.0 / d);
  Point v = rotate(PI / 2, c1.c - base);
  v = v / fabs(v);

  return { base + v * y, base - v * y };
}

pair<Point, Point> tangent(const Circle &c, const Point &p) {
  Real d = fabs(c.c - p);
  Real d2 = sqrt(d * d - c.r * c.r);
  Real a = acos(d2 / d);


  Point q = c.c - p;
  q = q / fabs(q);

//  cout << d << " " << d2 << " " << a << " " << q << endl;
  return {
    p + rotate(a, q) * d2,
    p + rotate(-a, q) * d2
  };
}

vector<Segment> common_tangent(Circle c1, Circle c2) {
  int isect = intersect(c1, c2);
  Real d = fabs(c1.c - c2.c);
  Point v = (c2.c - c1.c) / d;

  vector<Segment> res;

  if (isect == 0) {
    return {};
  } else if (isect == 1) {
    auto [p1, p2] = crosspoint(c1, Line(c1.c, c2.c));
    if (eq(fabs(p2 - c2.c), c2.r)) swap(p1, p2);

    Point v = p1 + rotate(PI/2, c2.c - p1);
    return { Segment(p1, v) };
  } else if (isect == 2) {
  } else if (isect == 3) {
    auto [p1, p2] = crosspoint(c1, c2);
    res.emplace_back(p1, rotate(PI / 2, c1.c - p1) + p1);
  } else {
    Real a = d * c1.r / (c1.r + c2.r);
    Point p = c1.c + v * a;

    Real d1 = sqrt(a * a - c1.r * c1.r), d2 = sqrt(norm(p - c2.c) - c2.r * c2.r);
    Real theta = acos(d1 / a);

//    cout << d << endl;
//    cout << a << " " << d1 << " " << d2 << " " << theta << ": " << p << endl;

    Point e = (c1.c - p) * (1.0 / fabs(c1.c - p));
    Point e1 = rotate(theta, e), e2 = rotate(-theta, e);

    res.emplace_back(p + e1 * d1, p - e1 * d2);
    res.emplace_back(p + e2 * d1, p - e2 * d2);
  }

  if (eq(c1.r, c2.r)) {
    Point e = rotate(PI / 2, v);
    res.push_back(Segment(c1.c + e * c1.r, c2.c + e * c1.r));
    res.push_back(Segment(c1.c - e * c1.r, c2.c - e * c1.r));
    return res;
  }

  if (c1.r > c2.r) swap(c1, c2);

  v = c1.c - c2.c;
  Point p = v * (1.0 / (c2.r - c1.r)) * c2.r + c2.c;

  auto [q1, q2] = tangent(c1, p);
  res.emplace_back(q1, crosspoint(c2, Line(p, q1)).first);
  res.emplace_back(q2, crosspoint(c2, Line(p, q2)).first);

  return res;
}

using Polygon = vector<Point>;

istream& operator>>(istream& is, Polygon &p) {
  for (int i = 0; i < p.size(); i++) is >> p[i];
  return is;
}

ostream& operator<<(ostream& os, Polygon &p) {
  for (int i = 0; i < p.size(); i++) os << p[i];
  return os;
}

Real area(const Polygon& p) {
  Real res = 0;
  for (int i = 0; i < p.size(); i++) {
    res += cross(p[i], p[(i + 1) % p.size()]);
  }
  return abs(res)/2;
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Point a=g[i]-p,b=g[(i+1)%n]-p;
    if(fabs(cross(a,b)) < EPS and dot(a,b) < EPS) return 1;
    if(a.imag()>b.imag()) swap(a,b);
    if(a.imag() < EPS and EPS < b.imag() and cross(a,b) > EPS ) {
//      cout << a << " --- " << b << ": " << cross(a, b) << endl;
      x = !x;
    }
  }
  return (x?2:0);
}

Polygon convex_hull(Polygon Q) {
  sort(ALL(Q));

  Polygon upper({Q[0]}), lower({Q[0]});

  rep(i, 1, Q.size()) {
    while (upper.size() >= 2) {
      int _ccw = ccw(upper[upper.size() - 2], upper[upper.size() - 1], Q[i]);
      if (_ccw == 1) {
        upper.pop_back();
      } else {
        break;
      }
    }
    if (upper.size() <= 1) {
      upper.push_back(Q[i]);
    } else if (upper.size() > 1) {
      int _ccw = ccw(upper[upper.size() - 2], upper[upper.size() - 1], Q[i]);
      if (_ccw == -1 || _ccw == -2) {
        upper.push_back(Q[i]);
      }
    }
  }
  rep(i, 1, Q.size()) {
    while (lower.size() >= 2) {
      int _ccw = ccw(lower[lower.size() - 2], lower[lower.size() - 1], Q[i]);
      if (_ccw == -1) {
        lower.pop_back();
      } else {
        break;
      }
    }

    if (lower.size() <= 1) {
      lower.push_back(Q[i]);
    } else if (lower.size() > 1) {
      int _ccw = ccw(lower[lower.size() - 2], lower[lower.size() - 1], Q[i]);
      if (_ccw == 1 || _ccw == -2) {
        lower.push_back(Q[i]);
      }
    }
  }

  Polygon ret;

  rep(i, 0, lower.size()) {
    ret.push_back(lower[i]);
//    cout << lower[i] << endl;
  }

//  cout << " | " << endl;

  rrep(i, 0, upper.size()) {
    if (!eq(lower[0], upper[i]) && !eq(lower.back(), upper[i]))
      ret.push_back(upper[i]);
//    cout << upper[i] << endl;
  }

  int start = 0;

//  cout << ret.size() << endl;
  rep(i, 0, ret.size()) {
    if (ret[i].imag() < ret[start].imag() || (eq(ret[i].imag(), ret[start].imag()) && ret[i].real() < ret[start].real())) {
      start = i;
    }
  }

  cout << ret.size() << endl;
  rep(i, 0, ret.size()) {
    auto p = ret[(i + start) % ret.size()];
    cout << (int)p.real() << " " << (int)p.imag() << endl;
  }

  return ret;
}

Real closest_pair(vector<Point> &pts, int l, int r) {
  int m = (l + r) / 2;
  if (r - l <= 1) {
    return INF;
  } else if (r - l == 2) {
    if (imag(pts[l]) > imag(pts[l + 1])) swap(pts[l], pts[l + 1]);
    return fabs(pts[l] - pts[l + 1]);
  }

  Real mid = pts[m].real();
  Real d = min(closest_pair(pts, l, m), closest_pair(pts, m, r));

  inplace_merge(pts.begin() + l, pts.begin() + m, pts.begin() + r, [](const Point &a, const Point& b) {
    return a.imag() < b.imag();
  });

  vector<Point> ret;

  for (int i = l; i < r; i++) {
    if (fabs(pts[i].real() - mid) >= d) continue;

    for (int j = ret.size() - 1; j >= 0; j--) {
      if (fabs(imag(ret[j]) - imag(pts[i])) >= d) break;
      chmin(d, fabs(ret[j] - pts[i]));
    }

    ret.emplace_back(pts[i]);
  }

  return d;
}

int main() {
  cout << fixed << setprecision(10);

  Real W, H;
  int N;
  while (cin >> W >> H >> N && N) {
    vector<Point> pts(2 * N);
    for (auto &p : pts) cin >> p;
    N += 2;
    int n = 2 * N;

    // ccw > 0 => 0 < theta <= pi

    Segment lft(Point(0, 0), Point(0, H)), rht(Point(W, 0), Point(W, H));
    pts.emplace_back(lft.a);
    pts.emplace_back(lft.b);
    pts.emplace_back(rht.a);
    pts.emplace_back(rht.b);
    Real res = 0;

    vector<Segment> half;
    auto is_half_line = [&](const Point &a, const Point &b) {
      int cnt[2] = {};
      int on = 0;
      rep(k, 0, n - 4) {
        int c= ccw(a, b, pts[k]);
        if (c != 0) cnt[c > 0]++;
        else on++;
      }

      return abs(cnt[0] - cnt[1]) <= on;
    };
    rep(i, 0, n) {
      rep(j, i + 1, n) {
        Line l = Line(pts[i], pts[j]);
        if (is_half_line(pts[i], pts[j])) {
          if (intersect(l, lft) && intersect(l, rht)) {
            half.emplace_back(crosspoint(l, lft), crosspoint(l, rht));
          }
        }
      }
    }

    sort(ALL(half), [&](const Segment& a, const Segment &b) {
      return a.a < b.a;
    });

    rep(i, 0, half.size() - 1) {
      Point m((half[i].a + half[i + 1].a) * 0.5);

//      cout << m << endl;
      vector<Real> ry;
      rep(j, 0, n) {
        if (is_half_line(m, pts[j]) && intersect(Line(m, pts[j]), rht)) {
//          ry.push_back(clamp(crosspoint(Line(m, pts[j]), rht).imag(), (Real)0.0, H));
          ry.push_back(crosspoint(Line(m, pts[j]), rht).imag());
//          cout << " ---- " << pts[j] << endl;
        }
      }
      sort(ALL(ry));
      if (ry.size() >= 2) {
//        cout << ry.back() spa ry.front() << " --- " << half[i + 1].a.imag() << " " << imag(half[i].a) << endl;
        res += (ry.back() - ry.front()) * (half[i + 1].a.imag() - half[i].a.imag());
      }
    }
    cout << res / H / H << endl;
  }
}
accuracy: 1
time_ms: 2040
memory_kb: 3604
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

constexpr double eps = 1e-10;

template <typename T>
struct Fraction {
    T num, den;
    Fraction(T num = 0, T den = 1) : num(num), den(den) { reduce(); }
    void reduce() {
        T g = std::gcd(num, den);
        num /= g, den /= g;
        if (den < 0) num = -num, den = -den;
    }
    Fraction& operator+=(const Fraction& rhs) {
        num = num*rhs.den + rhs.num*den;
        den *= rhs.den;
        reduce();
        return *this;
    }
    Fraction& operator-=(const Fraction& rhs) {
        num = num*rhs.den - rhs.num*den;
        den *= rhs.den;
        reduce();
        return *this;
    }
    Fraction& operator*=(const Fraction& rhs) {
        num *= rhs.num;
        den *= rhs.den;
        reduce();
        return *this;
    }
    Fraction& operator/=(const Fraction& rhs) {
        num *= rhs.den;
        den *= rhs.num;
        reduce();
        return *this;
    }
    Fraction operator-() const { return Fraction(-num, den); }
    Fraction operator+(const Fraction& rhs) const { return Fraction(*this) += rhs; }
    Fraction operator-(const Fraction& rhs) const { return Fraction(*this) -= rhs; }
    Fraction operator*(const Fraction& rhs) const { return Fraction(*this) *= rhs; }
    Fraction operator/(const Fraction& rhs) const { return Fraction(*this) /= rhs; }
    bool operator==(const Fraction& rhs) const { return num*rhs.den == rhs.num*den; }
    bool operator!=(const Fraction& rhs) const { return !(*this == rhs); }
    bool operator<(const Fraction& rhs) const { return num*rhs.den < rhs.num*den; };
    bool operator>(const Fraction& rhs) const { return num*rhs.den > rhs.num*den; };
    bool operator<=(const Fraction& rhs) const { return !(*this > rhs); };
    bool operator>=(const Fraction& rhs) const { return !(*this < rhs); };
    friend ostream &operator<<(ostream& os, const Fraction& p) { return os << p.num << "/" << p.den; }
};


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    while (true) {
        int W, H, N;
        cin >> W >> H >> N;
        if (W == 0) break;
        vector<pair<int, int>> pts(2*N);
        for (auto& x : pts) cin >> x.first >> x.second;
        sort(all(pts));
        pts.insert(pts.begin(), {0, 0});
        pts.insert(pts.begin()+1, {0, H});
        pts.push_back({W, 0});
        pts.push_back({W, H});
        vector<Fraction<int>> slopes;
        rep(i,0,pts.size()) rep(j,i+1,pts.size()) {
            if (pts[i].first == pts[j].first) continue;
            Fraction<int> slope(pts[j].second - pts[i].second, pts[j].first - pts[i].first);
            if (slope < Fraction(-H, W) || Fraction(H, W) < slope) continue;
            slopes.push_back(slope);
        }
        sort(all(slopes));
        slopes.erase(unique(all(slopes)), slopes.end());
        reverse(all(slopes));

        auto calc = [&](int n) {
            double l1 = -1, r1 = -1;
            double ans = 0;
            for (auto& m : slopes) {
                vector<double> ys;
                rep(i,2,pts.size()-2) {
                    ys.push_back(pts[i].second - 1.0*m.num/m.den*pts[i].first);
                }
                sort(all(ys));
                double l2 = ys[n];
                double r2 = l2 + 1.0*m.num/m.den*W;
                if (max(l2, r2) > H) {
                    double d = max(l2, r2) - H;
                    l2 -= d;
                    r2 -= d;
                }
                if (min(l2, r2) < -eps) {
                    continue;
                }

                if (l1 != -1 && l1+eps < l2) {
                    ans += r1*(l2-l1) + l1*(r1-r2) - (r1-r2)*(l1+l2)/2;
                }
                l1 = l2;
                r1 = r2;
            }
            ans /= H*H;
            return ans;
        };

        cout << calc(N) - calc(N-1) << endl;
    }
}
accuracy: 1
time_ms: 810
memory_kb: 3656
final_rank: 7

code_snippet: #include<bits/stdc++.h> 
using namespace std;
using ll=long long int;
//using Int=__int128;
#define ALL(A) A.begin(),A.end()
template<typename T1,typename T2> bool chmin(T1 &a,T2 b){if(a<=b)return 0; a=b; return 1;}
template<typename T1,typename T2> bool chmax(T1 &a,T2 b){if(a>=b)return 0; a=b; return 1;}
template<typename T> constexpr int bitUP(T x,int a){return (x>>a)&1;}
//→　↓　←　↑ 
int dh[4]={0,1,0,-1}, dw[4]={1,0,-1,0};
//右上から時計回り
//int dh[8]={-1,0,1,1,1,0,-1,-1}, dw[8]={1,1,1,0,-1,-1,-1,0};
//long double EPS = 1e-6;
//long double PI = acos(-1);
//const ll INF=(1LL<<62);
const int MAX=(1<<30);
constexpr ll MOD=1000000000+7;
//constexpr ll MOD=998244353;


inline void bin101(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(20);
}

using Graph=vector<vector<int>>;

template<typename T >
struct edge {
	int to;
	T cost;
	edge()=default;
	edge(int to, T cost) : to(to), cost(cost) {}

};
template<typename T>
using WeightGraph=vector<vector<edge<T>>>;

//要素数n 初期値x
template<typename T>
inline vector<T> vmake(size_t n,T x){
	return vector<T>(n,x);
}

//a,b,c,x data[a][b][c] 初期値x
template<typename... Args>
auto vmake(size_t n,Args... args){
	auto v=vmake(args...);
	return vector<decltype(v)>(n,move(v));
}

////////////////////////////
// マクロや型
////////////////////////////

using DD=long double;

const DD EPS=1e-9;
const DD INF=1e50;
const DD PI=acosl(-1.0);
#define EQ(a,b) (abs( (a) - (b) )<EPS) //a==b
#define LS(a,b) ( (a)+EPS<(b) ) //a<b
#define GR(a,b) ( (a)>(b)+EPS ) //a>b
#define LE(a,b) ( (a)<(b)+EPS ) //a<=b
#define GE(a,b) ( (a)>(b)-EPS ) //a>=b

#define X real()
#define Y imag()


//点
using Point=complex<DD>;
istream &operator>>(istream &is, Point &p) {
  DD x,y;
  is>>x>>y;
  p=Point(x,y);
  return is;
}

//点a→点bの線分
//aとbが等しい時、色々バグるから注意!
struct Segment{
    Point a,b;
    Segment()=default;
    Segment(Point a,Point b) :a(a),b(b){}
    Segment(DD ax,DD ay,DD bx,DD by):a(ax,ay),b(bx,by){}
    Segment(DD r,Point a) :a(a),b(a+polar((DD)1.0,r)){} 
};
using Line=Segment;

//円
struct Circle{
    Point p;
    DD r;
    Circle()=default;
    Circle(Point p,DD r):p(p),r(r){}
};

using Polygon=vector<Point>;

////////////////////////////
// 基本計算
////////////////////////////

//度→ラジアン
inline DD torad(const DD deg){return deg*PI/180;}
//ラジアン→度
inline DD todeg(const DD rad){return rad*180/PI;}
//内積 |a||b|cosθ
inline DD dot(const Point &a,const Point &b){return (conj(a)*b).X;}
//外積 |a||b|sinθ
inline DD cross(const Point &a,const Point &b){return (conj(a)*b).Y;}
//ベクトルpを反時計回りにtheta(ラジアン)回転
Point rotate(const Point &p,const DD theta){return p*Point(cos(theta),sin(theta));}

//余弦定理 cos(角度abc(ラジアン))を返す
//長さの対応に注意 ab:辺abの長さ
//verify:https://codeforces.com/gym/102056/problem/F
DD cosine_formula(const DD ab,const DD bc,const DD ca){
    return (ab*ab+bc*bc-ca*ca)/(2*ab*bc);
}

inline bool xy_sort(const Point &a,const Point &b){
    if(a.X+EPS<b.X) return true;
    if(EQ(a.X,b.X) && a.Y+EPS<b.Y) return true;
    return false;
}
inline bool yx_sort(const Point &a,const Point &b){
    if(a.Y+EPS<b.Y) return true;
    if(EQ(a.Y,b.Y) && a.X+EPS<b.X) return true;
    return false;
}
namespace std{
    inline bool operator<(const Point &a,const Point &b)noexcept{
        return xy_sort(a,b);
    }
}
//DDの比較関数
//map<DD,vector<pii>,DDcom>
struct DDcom{
    bool operator()(const DD a, const DD b) const noexcept {
        return a+EPS<b;
    }
};


////////////////////////////
// 平行や直交
////////////////////////////

bool isOrthogonal(const Point &a,const Point &b){
    return EQ(dot(a,b),0.0);
}
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool isOrthogonal(const Segment &s,const Segment &t){
    return EQ(dot(s.a-s.b,t.a-t.b),0.0);
}
bool isParallel(const Point &a,const Point &b){
    return EQ(cross(a,b),0.0);
}
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool isParallel(const Segment &s,const Segment &t){
    return EQ(cross(s.a-s.b,t.a-t.b),0);
}
//線分a→bに対して点cがどの位置にあるか
//反時計回り:1　時計回り:-1 直線上(a,b,c:-2 a,c,b:0 c,a,b:2)
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C
//線分a→bの端点にcがあるなら0と判定されるはず
int ccw(const Point &a,Point b,Point c){
    if(EQ(abs(b-c),0) or EQ(abs(a-c),0)) return 0;
    b-=a;c-=a;
    if(cross(b,c)>EPS) return 1;
    if(cross(b,c)<-EPS) return -1;
    if(dot(b,c)<-EPS) return 2;
    if(LS(norm(b),norm(c))) return -2;
    return 0;
}

////////////////////////////
// 射影と反射
////////////////////////////

//射影
//直線lに点pから垂線を引いたときの交点
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A
Point project(const Point &p,const Line &l){
    Point base=l.b-l.a;
    DD r=dot(p-l.a,base)/norm(base);
    return l.a+base*r;
}
//反射
//直線lに対して点pと対称な点
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B
Point reflect(const Point &p,const Line &l){
    return p+(project(p,l)-p)*(DD)2.0;
}
//反射
//直線lに対して線分sと対称な線分(直線でも使える)
//verify:https://onlinejudge.u-aizu.ac.jp/solutions/problem/1171/review/6009447/bin101/C++17
Segment reflect(const Segment &s,const Line &l){
    return Segment(reflect(s.a,l) , reflect(s.b,l));
}

////////////////////////////
// 点との距離
////////////////////////////

//点と直線の距離
DD DistPL(const Point &p,const Line &l){
    return abs(cross(l.b-l.a,p-l.a))/abs(l.b-l.a);
}
//点と線分の距離
DD DistPS(const Point &p,const Segment &s){
    if( dot(s.b-s.a,p-s.a)<0.0 ) return abs(p-s.a);
    if( dot(s.a-s.b,p-s.b)<0.0 ) return abs(p-s.b);
    return DistPL(p,s);
}

////////////////////////////
// 線分と直線
////////////////////////////

//線分a-b,c-dは交差するか?
//接する場合も交差すると判定
//接する場合は交差しないとするなら<=を<に変換
bool intersect(const Point &a,const Point &b,const Point &c,const Point &d){
    return(ccw(a,b,c)*ccw(a,b,d)<=0 && ccw(c,d,a)*ccw(c,d,b)<=0);
}
//線分s,tは交差するか？
//接する場合も交差すると判定
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B&lang=ja
//接する場合は交差しないとするならintersectの<=を<に変換
bool intersect(const Segment &s,const Segment &t){
    return intersect(s.a,s.b,t.a,t.b);
}
// 2直線の交点
// 線分の場合はintersectをしてから使う
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_C&lang=ja
Point crossPoint(const Line &s,const Line &t){
    Point base=t.b-t.a;
    DD d1=cross(base,t.a-s.a);
    DD d2=cross(base,s.b-s.a);
    if(EQ(d1,0) and EQ(d2,0)) return s.a; //同じ直線
    if(EQ(d2,0)) assert(false); //交点がない
    return s.a+d1/d2*(s.b-s.a);
}
//線分と線分の距離
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_D&lang=ja
DD Dist(const Segment &s,const Segment &t){
    if(intersect(s,t)) return 0.0;
    return min(min(DistPS(t.a,s),DistPS(t.b,s)),min(DistPS(s.a,t),DistPS(s.b,t)) );
}
bool issame(const Line &l,const Line &m){
    if (GR(abs(cross(m.a - l.a, l.b - l.a)),0) ) return false;
    if (GR(abs(cross(m.b - l.a, l.b - l.a)),0) ) return false;
    return true;
}

////////////////////////////
// 円
////////////////////////////
//直線lと円Cの交点
//l.aにより近い方がindexが小さい
//veirfy:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_D
vector<Point> crossPointLC(const Line &l,const Circle &c){
    vector<Point> ret;
    if(GR(DistPL(c.p,l),c.r)) return ret; //交点がないとき、空ベクトルを返す
    Point pr=project(c.p,l);
    Point e=(l.b-l.a)/(abs(l.b-l.a));
    DD base=sqrt(c.r*c.r-norm(pr-c.p));
    ret.push_back(pr-e*base);
    ret.push_back(pr+e*base);
    if(EQ(DistPL(c.p,l),c.r)) ret.pop_back(); //接するとき
    return ret;
}
//線分sと円cの交点
//交点がないときは空ベクトルを返す
//線分の端が交わる場合も交点とみなす
//s.aにより近い方がindexが小さい
vector<Point> crossPointSC(const Segment &s,const Circle &c){
    vector<Point> ret;
    if(DistPS(c.p,s)>c.r+EPS) return ret;
    auto koho=crossPointLC(s,c);
    for(auto p:koho){
        if(ccw(s.a,s.b,p)==0 or EQ(abs(p-s.a),0) or EQ(abs(p-s.b),0)) ret.push_back(p);
    }
    return ret;
}

//円aと円bの共通接線の数
//離れている:4 外接:3 交わる:2 内接:1 内包:0
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A
int intersect(const Circle &a,const Circle &b){
    DD d=abs(a.p-b.p);
    if(GR(d,a.r+b.r)) return 4;
    if(EQ(d,a.r+b.r)) return 3;
    if(EQ(d,abs(a.r-b.r))) return 1;
    if(LS(d,abs(a.r-b.r))) return 0;
    return 2;
}

//円aと円bの交点
//交点がないときは空ベクトルを返す
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_E
vector<Point> crossPoint(const Circle &a,const Circle &b){
    vector<Point> ret;
    if(GR(abs(a.p-b.p),a.r+b.r)) return ret;
    DD d=abs(a.p-b.p);
    DD s=acosl((a.r*a.r+d*d-b.r*b.r)/(2*a.r*d)); //0~π
    DD t=arg(b.p-a.p);
    if(EQ(a.r+b.r,d)) ret.push_back(a.p+polar(a.r,t));
    else ret.push_back(a.p+polar(a.r,t+s)),ret.push_back(a.p+polar(a.r,t-s));
    return ret;
}

//点pから円cに接線を引いたときの接点
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_F&lang=ja
vector<Point> TanLine(const Point &p,const Circle &c){
    vector<Point> ret;
    DD d=abs(p-c.p);
    if(LS(d,c.r)) return ret; //pがcの内部にある場合
    if(EQ(d,c.r)){
        ret.push_back(p);
        return ret; //円の線上にある場合
    } 
    return crossPoint(c,Circle(p,sqrt(d*d-c.r*c.r)));
}

//円a,bの共通接線
//https://www.slideshare.net/kujira16/ss-35861169
//Line.aは円aと接線の交点
//(接線と円bの交点)と(接線と円aの交点)が違う場合はLine.bは(接線と円bの交点)
//一致する場合は円aの中心からLine.aに向かうベクトルを反時計回りに90度回転したものを
//Line.aに足したもの
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_G
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2201
vector<Line> TanLine(const Circle &a,const Circle &b){
    DD d=abs(a.p-b.p);
    vector<Line> ret;
    //外接線
    if(intersect(a,b)>=2){
        if(EQ(a.r,b.r)){
            Point up=polar(a.r,arg(b.p-a.p)+PI/2);
            ret.emplace_back(a.p+up,b.p+up);
            ret.emplace_back(a.p-up,b.p-up);
        }else{
            Point q=(a.p*b.r-b.p*a.r)/(b.r-a.r);
            auto as=TanLine(q,a);
            auto bs=TanLine(q,b);
            assert(as.size()==2 and bs.size()==2);
            for(int i=0;i<2;i++){
                ret.emplace_back(as[i],bs[i]);
            }
        }
    }else if(intersect(a,b)==1){ //内接する場合
        Point dir;
        if(a.r>b.r) dir=polar(a.r,arg(b.p-a.p));
        else dir=polar(a.r,arg(a.p-b.p));
        ret.emplace_back(a.p+dir,a.p+dir+rotate(dir,PI/2));
    }
    //内接線
    if(GR(abs(a.p-b.p),a.r+b.r)){ //円が離れている場合
        Point q=a.p+(b.p-a.p)*a.r/(a.r+b.r);
        auto as=TanLine(q,a);
        auto bs=TanLine(q,b);
        assert(as.size()==2 and bs.size()==2);
        for(int i=0;i<2;i++){
            ret.emplace_back(as[i],bs[i]);
        }
    }else if(EQ(d,a.r+b.r)){ //円が接している場合
        Point dir=polar(a.r,arg(b.p-a.p));
        ret.emplace_back(a.p+dir,a.p+dir+rotate(dir,PI/2));
    }
    return ret;
}
//２つの円の共通部分の面積
//参考: https://tjkendev.github.io/procon-library/python/geometry/circles_intersection_area.html
//verify: https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=6005736#1
DD Area(const Circle &c1,const Circle &c2){
    DD cd=abs(c1.p-c2.p);
    if(LE(c1.r+c2.r,cd)) return 0; //円が離れている

    if(LE(cd,abs(c1.r-c2.r))) //片方の円が他方を包んでいる
        return min(c1.r,c2.r)*min(c1.r,c2.r)*PI;

    DD theta1=acosl(cosine_formula(c1.r,cd,c2.r));
    DD theta2=acosl(cosine_formula(c2.r,cd,c1.r));

    return c1.r*c1.r*theta1+c2.r*c2.r*theta2-c1.r*cd*sin(theta1);
}


////////////////////////////
// 三角形
////////////////////////////

//ヘロンの公式　三角形の面積を返す
//三角形が成立するか(平行ではないか)を忘れずに
DD Heron(const DD ad,const DD bd,const DD cd){
    DD s=(ad+bd+cd)/2;
    return sqrt(s*(s-ad)*(s-bd)*(s-cd));
}
//三角形の外接円
//isParallel()を使って三角形が成立するか(平行ではないか)を忘れずに
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_C
Circle CircumscribedCircle(const Point &a,const Point &b,const Point &c){
    Point bc=(b+c)/(DD)2.0;
    Line aa(bc,bc+rotate(c-b,PI/2));
    Point ab=(a+b)/(DD)2.0;
    Line cc(ab,ab+rotate(b-a,PI/2));
    Point p=crossPoint(aa,cc);
    return Circle(p,abs(a-p));
}
//三角形の内接円
//isParallel()を使って三角形が成立するか(平行ではないか)を忘れずに
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_B
Circle InCircle(const Point &a,const Point &b,const Point &c){
    Line aa(a,a+polar((DD)1.0,(arg(b-a)+arg(c-a))/(DD)2.0));
    Line bb(b,b+polar((DD)1.0,(arg(a-b)+arg(c-b))/(DD)2.0));
    Point p=crossPoint(aa,bb);
    return Circle(p,DistPL(p,Line(a,b)));
}

////////////////////////////
// 多角形
////////////////////////////

//点pが多角形gに対してどの位置にあるか
//中:2 辺上:1 外:0
//凸多角形である必要ない
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
int contains(const Point &p,const vector<Point> &g){
    int n=(int)g.size();
    int x=false;
    for(int i=0;i<n;i++){
        Point a=g[i]-p,b=g[(i+1)%n]-p;
        if(EQ(cross(a,b),0) && 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;
    }
    return (x?2:0);
}
//凸性判定
//多角形gは凸か？
//gは反時計回りでも時計回りでもいい
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_B
bool isConvex(const vector<Point> &g){
    int n=(int)g.size();
    if(n<=3) return true;
    int flag=0;
    int t;
    for(int i=0;i<n;i++){
        Point a(g[(i+1)%n]-g[i]),b(g[(i+2)%n]-g[i]);
        if(cross(a,b)>EPS) t=1;
        else if(cross(a,b)<-EPS) t=-1;
        else continue;
        if(flag==-t) return false;
        flag=t;
    }
    return true;
}

//凸包　アンドリューのアルゴリズム
//O(NlogN)
//反時計回りの多角形を返す
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A
vector<Point> ConvexHull(vector<Point> s,const bool on_edge){
    int j;
    if(on_edge) j=-1;
    else j=1;
    int sz=(int)s.size();
    if(sz<3) return s;
    sort(s.begin(),s.end(),yx_sort);

    int n=0;
    vector<Point> res(2*sz);
    for(int i=0;i<sz;i++){
        while(n>=2 && cross(res[n-1]-res[n-2],s[i]-res[n-2])<EPS*j){
            n--;
        }
        res[n]=s[i];
        n++;
    }
    int t=n+1;
    for(int i=sz-2;i>=0;i--){
        while(n>=t && cross(res[n-1]-res[n-2],s[i]-res[n-2])<EPS*j){
            n--;
        }
        res[n]=s[i];
        n++;
    }
    res.resize(n-1);
    return res;
}

//多角形g(凸でなくてもいい)の符号付き面積
//反時計回りの多角形なら正の値を返す　時計回りなら負
//O(N)
//https://imagingsolution.net/math/calc_n_point_area/
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_A
DD Area(const vector<Point> &g){
    DD ret=0.0;
    int n=(int)g.size();
    for(int i=0;i<n;i++){
        ret+=cross(g[i],g[(i+1)%n]);
    }
    return ret/2.0;
}

//凸多角形gを直線lで切断
//直線の左側(向きを考慮)にできる凸多角形を返す
//多角形gが反時計回りならば、反時計回りで返す(時計回りなら時計回り)
//直線上の頂点を含む線分の交点は含めてない
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_C
vector<Point> ConvexCut(const vector<Point> &g,const Line &l){
    vector<Point> ret;
    int gz=(int)g.size();
    for(int i=0;i<gz;i++){
        Point now=g[i],next=g[(i+1)%gz];
        if(ccw(l.a,l.b,now)!=-1) ret.push_back(now);
        if(EQ(DistPL(now,l),0) or EQ(DistPL(next,l),0)) continue;
        if(ccw(l.a,l.b,now)*ccw(l.a,l.b,next)<0){
            ret.push_back(crossPoint(Line(now,next),l));
        }
    }
    return ret;
}
//部品
inline DD calc(const Point &a,const Point &b,const DD &r,const bool triangle){
    if(triangle) return cross(a,b);
    else return r*r*arg(b/a);
}
//部品
DD calcArea(const DD &r,const Point &a,const Point &b){
    if(EQ(abs(a-b),0)) return 0;
    bool ina=(abs(a)<r+EPS);
    bool inb=(abs(b)<r+EPS);
    if(ina && inb) return cross(a,b);
    auto cr=crossPointSC(Segment(a,b),Circle(Point(0,0),r));
    if(cr.empty()) return calc(a,b,r,false);
    auto s=cr[0],t=cr.back();
    return calc(s,t,r,true)+calc(a,s,r,ina)+calc(t,b,r,inb);
}
//円と多角形の共通部分の面積
//多角形が反時計回りならば正の値を返す
//凸多角形でなくても大丈夫
//http://drken1215.hatenablog.com/entry/2020/02/02/091000
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_H&lang=ja
DD Area(const Circle &c,const vector<Point> &g){
    DD ret=0.0;
    int gz=g.size();
    if(gz<=2) return ret;
    for(int i=0;i<gz;i++){
        Point a=g[i]-c.p,b=g[(i+1)%gz]-c.p;
        ret+=calcArea(c.r,g[i]-c.p,g[(i+1)%gz]-c.p);
    }
    return ret/2.0;
}

//点と多角形の距離
//点が多角形の中にあるなら0
DD Dist(const Point &a,const vector<Point> &b){
	if(b.size()==1) return abs(a-b[0]);
	if(contains(a,b)>=1) return 0.0L;
	DD ret=INF;
	for(int i=0;i<b.size();i++){
		chmin(ret,DistPS(a,Segment(b[i],b[(i+1)%b.size()])));
	}
	return ret;
}

//多角形と多角形の距離
//どちらかが内側に入っていたら0
//全ての線分の組み合わせの距離を求めて、その最小が答え
//O(size(a)*size(b))
//sizeが1の時は点との距離になる
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2827
DD Dist(const vector<Point> &a,const vector<Point> &b){
	DD ret=INF;
	if(a.size()==1) return Dist(a[0],b);
	if(b.size()==1) return Dist(b[0],a);

	if(contains(a[0],b)>=1) return 0.0L;
	if(contains(b[0],a)>=1) return 0.0L;

	for(int i=0;i<a.size();i++){
		for(int j=0;j<b.size();j++){
			Segment sa(a[i],a[(i+1)%a.size()]);
			Segment sb(b[j],b[(j+1)%b.size()]);
			chmin(ret,Dist(sa,sb));
		}
	}
	return ret;
}

////////////////////////////
// 最近(遠)点間距離
////////////////////////////
//部品
DD RecClosetPair(const vector<Point>::iterator it,const int n){
    if(n<=1) return INF;
    int m=n/2;
    DD x=it[m].X;
    DD d=min(RecClosetPair(it,m),RecClosetPair(it+m,n-m));
    inplace_merge(it,it+m,it+n,yx_sort);
    vector<Point> v;
    for(int i=0;i<n;i++){
        if(abs(it[i].X-x)>=d) continue;
        for(int j=0;j<v.size();j++){
            DD dy=it[i].Y-v[(int)v.size()-1-j].Y;
            if(dy>=d) break;
            DD dx=it[i].X-v[(int)v.size()-1-j].X;
            d=min(d,sqrt(dx*dx+dy*dy));
        }
        v.push_back(it[i]);
    }
    return d;
}
//最近点対の距離
//点が1つのときINFを返す
//O(NlogN)
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_5_A
DD ClosetPair(vector<Point> g){
    sort(g.begin(),g.end(),xy_sort);
    return RecClosetPair(g.begin(),g.size());
}

//最遠頂点間
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_B
DD Diameter(vector<Point> g){
    g=ConvexHull(g,1);
    int gz=g.size();
    int m=0,M=0;
    for(int i=1;i<gz;i++){
        if(g[i].Y<g[m].Y) m=i;
        if(g[i].Y>g[M].Y) M=i;
    }
    DD ret=0;
    int sm=m,sM=M;
    while(m!=sM || M!=sm){
        ret=max(ret,norm(g[m]-g[M]));
        if(cross(g[(m+1)%gz]-g[m],g[(M+1)%gz]-g[M])<0) m=(m+1)%gz;
        else M=(M+1)%gz;
    }
    return sqrt(ret);
}
//動的凸包
//辺上にある点は含めない
//verify:https://atcoder.jp/contests/geocon2013/tasks/geocon2013_c
struct DynamicConvex{
	set<Point> up,down;
	DynamicConvex(){}
 
	bool isContain(set<Point> &pol,Point p){
		if(pol.size()==0) return false;
		if(pol.size()==1){
			Point q=*begin(pol);
			return EQ(q.X,p.X) and GE(q.Y,p.Y);
		}
		assert(pol.size()>=2);
        auto left=begin(pol);
        auto right=(--end(pol));
        if(LS(p.X,left->X) or GR(p.X,right->X)) return false;
        
        
        auto q1=pol.upper_bound(Point(p.X,INF));
        if(q1==end(pol)){
            return GE(right->Y,p.Y);
        }
        auto q2=q1--; //q1が範囲外になるのは最初に弾いてる
        return GE(cross(p-*q1,*q2-*q1),0.0);
	}
    bool isContain(Point p){
        if(not isContain(up,p)) return false;
        if(not isContain(down,Point(p.X,-p.Y))) return false;
        return true;
    }
 
	void add(set<Point> &pol,Point p){
		if(pol.size()==0){
			pol.insert(p);
			return;
		}
		if(pol.size()==1){
            Point q=*begin(pol);
			if(EQ(q.X,p.X)){
                pol.clear();
                pol.insert(max(p,q));
			}else{
				pol.insert(p);
			}
            return;
		}
        assert(pol.size()>=2);
        if(isContain(pol,p)) return;
        //left
        auto q1=pol.upper_bound(Point(p.X,INF));
        if(q1!=begin(pol)){
            q1--;
            while(pol.size()>=1 and q1!=begin(pol)){
                auto q2=q1--;
                if(GR(cross(*q2-p,*q1-p),0)) break;
                pol.erase(q2);
            }
        }
        //right
        q1=pol.lower_bound(Point(p.X,-INF));
        if(q1!=end(pol)){
            while(pol.size()>1 and q1!=--end(pol)){
                auto q2=q1++;
                if(GR(cross(*q1-p,*q2-p),0.0)) break;
                pol.erase(q2);
            }
        }
        pol.insert(p);
	}
 
	void add(Point p){
		add(up,p);
		add(down,Point(p.X,-p.Y)); //upと同じように処理をしたいから
	}
};

//垂直二等分線
//p-↑-q こんなかんじ
//voronoiで使う
Line bisector(const Point &p, const Point &q) {
    Point c=(p+q)/DD(2.0);
    Point v=rotate(q-p,PI/2);
    v/=abs(v);
    return Line(c-v,c+v);
}

//ボロノイ図
//pol:全体 ps:点の集合 id:中心となる点の添字 pp:中心となる点
//計算量: pol.size()*ps.size()
//verify: https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=6005648#1
vector<Point> voronoi(Polygon pol,const vector<Point> &ps,int id=-1,const Point pp=Point()){
    Point p;
    if(id!=-1) p=ps[id];
    else p=pp;
    for(size_t i=0;i<ps.size();i++){
        if(i==id) continue;
        Line l=bisector(p,ps[i]);
        pol=ConvexCut(pol,l);
    }
    return pol;
}


void solve(){
while(true){
    //考える必要があるイベント
    //いちご2つを結んだ線
    //いちごと角を結んだ線
    int N;
    DD W,H;
    cin>>W>>H>>N;
    if(N==0) return;
    vector<Point> straw(N*2);
    for(int i=0;i<N*2;i++) cin>>straw[i];
    vector<DD> event;
    Segment Y0(Point(0,0),Point(0,H));
    Segment Y1(Point(W,0),Point(W,H));
//いちご2つを結んだ線
    for(int i=0;i<N*2;i++){
        for(int j=i+1;j<N*2;j++){
            Line l(straw[i],straw[j]);
            if(isParallel(l,Y0)) continue;
            auto x=crossPoint(Y0,l);
            if(ccw(Y0.a,Y0.b,x)!=0) continue;
            event.push_back(x.Y);
        }
    }
    vector<Point> kado={Point(W,0),Point(W,H)};
//いちごと角を結んだ線
    for(int i=0;i<N*2;i++){
        if(EQ(straw[i].X,0)){
            event.push_back(straw[i].Y);
            event.push_back(straw[i].Y);
            continue;
        }
        for(auto x:kado){
            Line l(straw[i],x);
            if(isParallel(l,Y0)) continue;
            //cerr<<"do"<<endl;
            auto y=crossPoint(Y0,l);
            if(ccw(Y0.a,Y0.b,y)!=0) continue;
            event.push_back(y.Y);
        }
    }
    event.push_back(0);
    event.push_back(H);
    int sz=event.size();
    sort(ALL(event));
    vector<DD> ans(event.size());
    int id=0;

    for(size_t I=0;I<event.size();I++){
        auto y=event[I];
        Point p(0,y);
        vector<DD> v;
        for(int i=0;i<N*2;i++){
            if(abs(p-straw[i])<EPS){
                if(I and EQ(event[I]-event[I-1],0)) v.push_back(-PI/2);
                else v.push_back(PI/2);
            }else v.push_back(arg(straw[i]-p));
        }
        sort(v.begin(),v.end());
        Segment s(p,p+polar(DD(1),v[N-1]));
        Segment t(p,p+polar(DD(1),v[N]));
        DD u=-1100,d=1100;
        if(isParallel(Y1,s)==false) u=crossPoint(Y1,s).Y;
        if(isParallel(Y1,t)==false) d=crossPoint(Y1,t).Y;
        ans[id++]=max(0.0L,min(d,H))-max(DD(0),min(u,H));
        //chmax(ans[id-1],0.0L);
    }
    DD x=0;
    for(size_t i=1;i<event.size();i++){
        x+=(event[i]-event[i-1])*(ans[i]+ans[i-1])/2;
    }
    cout<<x/H/H<<endl;
}
}

int main(){
    bin101();
    int T=1;
    //cin>>T;
    while(T--) solve();
}
accuracy: 1
time_ms: 4150
memory_kb: 4264
final_rank: 19

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

int main(){
double W,H;
int N;
while(cin>>W>>H>>N,N){
vector<double>X(N*2),Y(N*2),L{0,H};
for(int i=0;i<N*2;i++){
cin>>X[i]>>Y[i];
if(X[i]!=W){
L.emplace_back(Y[i]/(W-X[i])*W);
L.emplace_back(H+(Y[i]-H)/(W-X[i])*W);
}
for(int j=0;j<i;j++)
if(X[i]!=X[j])
L.emplace_back(Y[j]+(Y[i]-Y[j])/(X[j]-X[i])*X[j]);
}
sort(begin(L),end(L));
double ans=0;
for(int i=0;i<(int)L.size()-1;i++){
double mid=(L[i]+L[i+1])/2;
if(clamp(mid,0.,H)!=mid)
continue;
vector<double>R(N*2);
for(int j=0;j<N*2;j++)
R[j]=clamp(X[j]?mid+(Y[j]-mid)/X[j]*W:(mid<Y[j]?H:0),0.,H);
sort(begin(R),end(R));
ans+=(L[i+1]-L[i])*(R[N]-R[N-1]);
}
cout<<fixed<<setprecision(10)<<ans/H/H<<endl;
}
}
accuracy: 1
time_ms: 310
memory_kb: 3844
final_rank: 10

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

int main() {
    double W, H;
    int N;
    while (cin >> W >> H >> N, N) {
        vector<double> X(N * 2), Y(N * 2), L{0, H};
        for (int i = 0; i < N * 2; i++) {
            cin >> X[i] >> Y[i];
            if (X[i] != W) {
                L.emplace_back(Y[i] / (W - X[i]) * W);
                L.emplace_back(H + (Y[i] - H) / (W - X[i]) * W);
            }
            for (int j = 0; j < i; j++)
                if (X[i] != X[j])
                    L.emplace_back(Y[j] + (Y[i] - Y[j]) / (X[j] - X[i]) * X[j]);
        }
        sort(begin(L), end(L));
        double ans = 0;
        for (int i = 0; i < (int)L.size() - 1; i++) {
            double mid = (L[i] + L[i + 1]) / 2;
            if (clamp(mid, 0., H) != mid)
                continue;
            vector<double> R(N * 2);
            for (int j = 0; j < N * 2; j++)
                R[j] = clamp(X[j] ? mid + (Y[j] - mid) / X[j] * W : (mid < Y[j] ? H : 0), 0., H);
            sort(begin(R), end(R));
            ans += (L[i + 1] - L[i]) * (R[N] - R[N - 1]);
        }
        cout << fixed << setprecision(10) << ans / H / H << endl;
    }
}
accuracy: 1
time_ms: 310
memory_kb: 3756
final_rank: 9

code_snippet: /*	author:  Kite_kuma
	created: 2021.08.18 20:59:03 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region geometry

using Real = long double;
using R = Real;
using Point = std::complex<Real>;
using Vec = Point;
const Real EPS = 1e-10, PI = acos(-1);

inline bool eq(const Real &a, const Real &b) { return fabs(b - a) < EPS; }
inline bool eq(const Point &a, const Point &b) { return fabs(b - a) < EPS; }
/*
	-1: a < b
	0 : a == b
	1 : a > b
*/
inline int compare(const Real &a, const Real &b) { return eq(a, b) ? 0 : a < b ? -1 : 1; }

namespace std {
const Point operator*(const Point &p, const Real &d) { return Point(real(p) * d, imag(p) * d); }
}  // namespace std

std::istream &operator>>(std::istream &is, Point &p) {
	Real a, b;
	is >> a >> b;
	p = Point(a, b);
	return is;
}
std::ostream &operator<<(std::ostream &os, Point &p) { return os << std::fixed << std::setprecision(10) << p.real() << " " << p.imag(); }

// rotate point 'p' for counter clockwise direction
const Point rotate(const Real &theta, const Point &p) {
	return Point(cos(theta) * p.real() - sin(theta) * p.imag(), sin(theta) * p.real() + cos(theta) * p.imag());
}

const Real radian_to_degree(const Real &r) { return (r * 180.0 / PI); }

const Real degree_to_radian(const Real &d) { return (d * PI / 180.0); }

// get angle a-b-c (<pi)
const Real get_angle(const Point &a, const Point &b, const Point &c) {
	const Point v(a - b), w(c - b);
	Real theta = fabs(atan2(w.imag(), w.real()) - atan2(v.imag(), v.real()));
	return std::min(theta, 2 * PI - theta);
}

namespace std {
bool operator<(const Point &a, const Point &b) { return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag(); }
}  // namespace std

struct Line {
	Point a, b;

	Line() = default;

	Line(Point a, Point b) : a(a), b(b) {}

	Line(Real A, Real B, Real C)  // Ax + By = C
	{
		if(eq(A, 0))
			a = Point(0, C / B), b = Point(1, C / B);
		else if(eq(B, 0))
			b = Point(C / A, 0), b = Point(C / A, 1);
		else
			a = Point(0, C / B), b = Point(C / A, 0);
	}

	friend std::ostream &operator<<(std::ostream &os, Line &p) { return os << p.a << " -- " << p.b; }

	friend std::istream &operator>>(std::istream &is, Line &a) { return is >> a.a >> a.b; }
};

struct Segment : Line {
	Segment() = default;

	Segment(Point a, Point b) : Line(a, b) {}
};

struct Circle {
	Point p;
	Real r;

	Circle() = default;

	Circle(Point p, Real r) : p(p), r(r) {}
};

using Points = std::vector<Point>;
using Polygon = std::vector<Point>;
using Segments = std::vector<Segment>;
using Lines = std::vector<Line>;
using Circles = std::vector<Circle>;

const Real cross(const Point &a, const Point &b) { return real(a) * imag(b) - imag(a) * real(b); }
const Real dot(const Point &a, const Point &b) { return real(a) * real(b) + imag(a) * imag(b); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C
const int ccw(const Point &a, Point b, Point c) {
	b = b - a, c = c - a;
	if(cross(b, c) > EPS) return +1;		// "COUNTER_CLOCKWISE"
	if(cross(b, c) < -EPS) return -1;		// "CLOCKWISE"
	if(dot(b, c) < -EPS) return +2;			// "ONLINE_BACK"
	if(norm(b) + EPS < norm(c)) return -2;	// "ONLINE_FRONT"
	return 0;								// "ON_SEGMENT"
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool parallel(const Line &a, const Line &b) { return eq(cross(a.b - a.a, b.b - b.a), 0.0); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool orthogonal(const Line &a, const Line &b) { return eq(dot(a.a - a.b, b.a - b.b), 0.0); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A
Point projection(const Line &l, const Point &p) {
	double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + (l.a - l.b) * t;
}

Point projection(const Segment &l, const Point &p) {
	double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + (l.a - l.b) * t;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B
Point reflection(const Line &l, const Point &p) { return projection(l, p) * 2.0 - p; }

int intersect(const Line &l, const Point &p) { return int(abs(ccw(l.a, l.b, p)) != 1); }

int intersect(const Line &l, const Line &m) {
	if(intersect(l, m.a) && intersect(l, m.b)) return -1;
	return int(abs(cross(l.b - l.a, m.b - m.a)) > EPS);
}

int intersect(const Segment &s, const Point &p) { return int(ccw(s.a, s.b, p) == 0); }

int intersect(const Line &l, const Segment &s) {
	if(intersect(l, s.a) && intersect(l, s.b)) return -1;
	return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < EPS;
}

Real distance(const Line &l, const Point &p);

int intersect(const Circle &c, const Line &l) {
	Real d = c.r - distance(l, c.p);
	return fabs(d) < EPS ? 1 : d > 0. ? 2 : 0;
}

int intersect(const Circle &c, const Point &p) { return int(abs(abs(p - c.p) - c.r) < EPS); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
int intersect(const Segment &s, const Segment &t) {
	if(eq(s.a, s.b)) return intersect(t, s.a);
	if(intersect(Line(s), t.a) && intersect(Line(s), t.b) &&
	   std::max(std::min(s.a, s.b), std::min(t.a, t.b)) < std::min(std::max(s.a, s.b), std::max(t.a, t.b)))
		return -1;
	return int(ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0);
}

int intersect(const Circle &c, const Segment &l) {
	const Point h = projection(l, c.p);
	if(norm(h - c.p) - c.r * c.r > EPS) return 0;
	auto d1 = abs(c.p - l.a), d2 = abs(c.p - l.b);
	if(compare(d1, c.r) == -1 && compare(d2, c.r) == -1) return 0;
	if(d1 < c.r - EPS && d2 > c.r - EPS || d1 > c.r - EPS && d2 < c.r - EPS) return 1;
	return dot(l.a - h, l.b - h) < 0 ? 2 : 0;
}

Real distance(const Point &a, const Point &b);

int number_of_common_tangents(const Circle &c1, const Circle &c2) {
	Real r1 = std::min(c1.r, c2.r), r2 = std::max(c1.r, c2.r), d = distance(c1.p, c2.p);
	int com = compare(r1 + r2, d);
	return com == 1 ? compare(d + r1, r2) + 1 : 3 - com;
	// if(c1.r < c2.r) swap(c1, c2);
	// Real d = abs(c1.p - c2.p);
	// if(compare(c1.r + c2.r, d) == -1) return 4;
	// if(eq(c1.r + c2.r, d)) return 3;
	// if(compare(c1.r - c2.r, d) == -1) return 2;
	// return int(eq(c1.r - c2.r, d));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A&lang=jp
int intersect(const Circle &c1, const Circle &c2) { return 2 - abs(2 - number_of_common_tangents(c1, c2)); }

Real distance(const Point &a, const Point &b) { return abs(a - b); }

Real distance(const Line &l, const Point &p) { return abs(p - projection(l, p)); }

Real distance(const Line &l, const Line &m) { return intersect(l, m) ? 0 : distance(l, m.a); }

Real distance(const Segment &s, const Point &p) {
	Point r = projection(s, p);
	return intersect(s, r) ? distance(r, p) : std::min(abs(s.a - p), abs(s.b - p));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_D
Real distance(const Segment &a, const Segment &b) {
	if(intersect(a, b)) return 0;
	return std::min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}

Real distance(const Line &l, const Segment &s) {
	if(intersect(l, s)) return 0;
	return std::min(distance(l, s.a), distance(l, s.b));
}

Point crosspoint(const Line &l, const Line &m) {
	Real A = cross(l.b - l.a, m.b - m.a);
	Real B = cross(l.b - l.a, l.b - m.a);
	if(eq(abs(A), 0.0) && eq(abs(B), 0.0)) return m.a;
	return m.a + (m.b - m.a) * B / A;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_C
Point crosspoint(const Segment &l, const Segment &m) { return crosspoint(Line(l), Line(m)); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_D
std::pair<Point, Point> crosspoint(const Circle &c, const Line l) {
	Point pr = projection(l, c.p);
	if(eq(distance(l, c.p), c.r)) return {pr, pr};
	Vec v = (l.b - l.a) / abs(l.b - l.a) * sqrt(c.r * c.r - norm(pr - c.p));
	return make_pair(pr - v, pr + v);
	// Vec e = (l.b - l.a) / abs(l.b - l.a);
	// double base = sqrt(c.r * c.r - norm(pr - c.p));
	// return {pr - e * base, pr + e * base};
}

std::pair<Point, Point> crosspoint(const Circle &c, const Segment &l) {
	if(intersect(c, l) == 2) return crosspoint(c, Line(l.a, l.b));
	auto ret = crosspoint(c, Line(l.a, l.b));
	if(dot(l.a - ret.first, l.b - ret.first) < EPS)
		ret.second = ret.first;
	else
		ret.first = ret.second;
	return ret;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_E
std::pair<Point, Point> crosspoint(const Circle &c1, const Circle &c2) {
	Real d = abs(c1.p - c2.p);
	Real a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));  // cosine theorem
	Real t = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	Point p1 = c1.p + Point(cos(t + a) * c1.r, sin(t + a) * c1.r);
	Point p2 = c1.p + Point(cos(t - a) * c1.r, sin(t - a) * c1.r);
	return make_pair(p1, p2);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_F
// "点 p を通る円 c の接線"の接点2つ
std::pair<Point, Point> tangent(const Circle &c1, const Point &p2) {
	return crosspoint(c1, Circle(p2, sqrt(norm(c1.p - p2) - c1.r * c1.r)));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_G
// 円 c1, c2 の共通接線
Lines tangent(Circle c1, Circle c2) {
	Lines ret;
	if(c1.r < c2.r) std::swap(c1, c2);
	Real g = norm(c1.p - c2.p);
	if(eq(g, 0)) return ret;
	Vec u = (c2.p - c1.p) / Real(sqrt(g));
	Vec v = rotate(PI * 0.5, u);
	for(int s : {-1, 1}) {
		Real h = (c1.r + s * c2.r) / sqrt(g);
		if(eq(1 - h * h, 0)) {
			ret.emplace_back(c1.p + u * c1.r, c1.p + (u + v) * c1.r);
		} else if(1 - h * h > 0) {
			Point uu = u * h, vv = v * sqrt(1 - h * h);
			ret.emplace_back(c1.p + (uu + vv) * c1.r, c2.p - (uu + vv) * c2.r * s);
			ret.emplace_back(c1.p + (uu - vv) * c1.r, c2.p - (uu - vv) * c2.r * s);
		}
	}
	return ret;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_B
bool is_convex(const Polygon &p, bool pi_is_ok = false) {
	int n = p.size();
	if(pi_is_ok) {
		for(int i = 0; i < n; i++)
			if(ccw(p[i], p[(i + 1) % n], p[(i + 2) % n]) == -1) return false;
	} else {
		for(int i = 0; i < n; i++)
			if(ccw(p[i], p[(i + 1) % n], p[(i + 2) % n]) != 1) return false;
	}
	return true;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A
Polygon convex_hull(Polygon &p, bool pi_is_ok = false) {
	int n = (int)p.size(), k = 0;
	if(n <= 2) return p;
	sort(p.begin(), p.end());
	Points ch(2 * n);
	if(pi_is_ok) {
		for(int i = 0; i < n; ch[k++] = p[i++])
			while(k >= 2 && ccw(ch[k - 2], ch[k - 1], p[i]) == -1) --k;
		for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--])
			while(k >= t && ccw(ch[k - 2], ch[k - 1], p[i]) == -1) --k;
	} else {
		for(int i = 0; i < n; ch[k++] = p[i++])
			while(k >= 2 && ccw(ch[k - 2], ch[k - 1], p[i]) != 1) --k;
		for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--])
			while(k >= t && ccw(ch[k - 2], ch[k - 1], p[i]) != 1) --k;
	}
	ch.resize(k - 1);
	return ch;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
enum { OUT, ON, IN };
int contains(const Polygon &Q, const Point &p) {
	bool in = false;
	const Real p_y = p.imag();
	for(int i = 0; i < Q.size(); i++) {
		Point a = Q[i], b = Q[(i + 1) % Q.size()];
		if(ccw(a, b, p) == 0) return ON;
		if(a.imag() > b.imag()) swap(a, b);
		if(a.imag() <= p_y && p_y < b.imag() && cross(a - p, b - p) < 0) in = !in;
	}
	return in ? IN : OUT;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1033
// 線分の重複除去
void merge_segments(std::vector<Segment> &segs) {
	auto merge_if_able = [](Segment &s1, const Segment &s2) {
		if(abs(cross(s1.b - s1.a, s2.b - s2.a)) > EPS) return false;
		if(ccw(s1.a, s2.a, s1.b) == 1 || ccw(s1.a, s2.a, s1.b) == -1) return false;
		if(ccw(s1.a, s1.b, s2.a) == -2 || ccw(s2.a, s2.b, s1.a) == -2) return false;
		s1 = Segment(min(s1.a, s2.a), max(s1.b, s2.b));
		return true;
	};

	for(int i = 0; i < segs.size(); i++) {
		if(segs[i].b < segs[i].a) swap(segs[i].a, segs[i].b);
	}
	for(int i = 0; i < segs.size(); i++) {
		for(int j = i + 1; j < segs.size(); j++) {
			if(merge_if_able(segs[i], segs[j])) {
				segs[j--] = segs.back(), segs.pop_back();
			}
		}
	}
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1033
// 線分アレンジメント
// 任意の2線分の交点を頂点としたグラフを構築する
std::vector<std::vector<int>> segment_arrangement(std::vector<Segment> &segs, std::vector<Point> &ps) {
	std::vector<std::vector<int>> g;
	int N = (int)segs.size();
	for(int i = 0; i < N; i++) {
		ps.emplace_back(segs[i].a);
		ps.emplace_back(segs[i].b);
		for(int j = i + 1; j < N; j++) {
			const Point p1 = segs[i].b - segs[i].a;
			const Point p2 = segs[j].b - segs[j].a;
			if(eq(cross(p1, p2), 0)) continue;	// " == 0" となっていたのを訂正
			if(intersect(segs[i], segs[j])) {
				ps.emplace_back(crosspoint(segs[i], segs[j]));
			}
		}
	}
	sort(begin(ps), end(ps));
	ps.erase(unique(begin(ps), end(ps)), end(ps));	// 誤差?

	int M = (int)ps.size();
	g.resize(M);
	for(int i = 0; i < N; i++) {
		std::vector<int> vec;
		for(int j = 0; j < M; j++) {
			if(intersect(segs[i], ps[j])) {
				vec.emplace_back(j);
			}
		}
		for(int j = 1; j < vec.size(); j++) {
			g[vec[j - 1]].push_back(vec[j]);
			g[vec[j]].push_back(vec[j - 1]);
		}
	}
	return (g);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_C
// 凸多角形の切断
// 直線 l.a-l.b で切断しその左側にできる凸多角形を返す
Polygon convex_cut(const Polygon &U, Line l) {
	Polygon ret;
	for(int i = 0; i < U.size(); i++) {
		Point now = U[i], nxt = U[(i + 1) % U.size()];
		if(ccw(l.a, l.b, now) != -1) ret.push_back(now);
		if(ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) == -1) ret.push_back(crosspoint(Line(now, nxt), l));
	}
	return ret;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_A
// 多角形の面積
Real area(const Polygon &p) {
	Real A = 0;
	for(int i = 0; i < p.size(); ++i) {
		A += cross(p[i], p[(i + 1) % p.size()]);
	}
	return A * 0.5;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_H
// 円と多角形の共通部分の面積
Real area(const Polygon &p, const Circle &c) {
	if(p.size() < 3) return 0.0;
	auto cross_area = [&c](auto cross_area, const Point &a, const Point &b) -> Real {
		Point va = c.p - a, vb = c.p - b;
		Real f = cross(va, vb), ret = 0.0;
		if(eq(f, 0.0)) return ret;
		if(std::max(abs(va), abs(vb)) < c.r + EPS) return f;
		if(distance(Segment(a, b), c.p) > c.r - EPS) return c.r * c.r * arg(vb * conj(va));
		auto u = crosspoint(c, Segment(a, b));
		std::vector<Point> tot{a, u.first, u.second, b};
		for(int i = 0; i + 1 < tot.size(); i++) ret += cross_area(cross_area, tot[i], tot[i + 1]);
		return ret;
	};
	Real A = 0;
	for(int i = 0; i < p.size(); i++) {
		A += cross_area(cross_area, p[i], p[(i + 1) % p.size()]);
	}
	return A * 0.5;
}

#pragma endregion

void solve(int cnt) {
	int w, h, n;
	cin >> w >> h >> n;

	if(w + h + n == 0) exit(0);
	int n2 = n + n;

	Points ps(n2);
	rep(i, n2) { cin >> ps[i]; }

	if(cnt == 11) {
		debug(ps);
	}

	Points ps_all = ps;
	ps_all.emplace_back(0, 0);
	ps_all.emplace_back(0, h);
	ps_all.emplace_back(w, 0);
	ps_all.emplace_back(w, h);

	V<R> ys;

	Line leftside(Point(0, 0), Point(0, 1));
	Line rightside(Point(w, 0), Point(w, 1));

	rep(i, int(ps_all.size())) {
		rep(j, i + 1, int(ps_all.size())) {
			Point &p = ps_all[i], &r = ps_all[j];
			// if(eq(p.real(), r.real())) continue;
			Line ln(p, r);
			if(intersect(ln, leftside) != 1) continue;
			Real y = crosspoint(leftside, ln).imag();
			if(isnan(y)) continue;
			if(-EPS <= y && y <= h + EPS) ys.push_back(y);
		}
		ys.push_back(ps_all[i].imag());
	}
	sort(all(ys));

	auto kukan = [&](R y, Point &dn, Point &up) {
		Point pt(0, y);
		R low, high;
		if(eq(dn.real(), 0)) {
			low = 0;
		} else {
			low = max(R(0), crosspoint(rightside, Line(dn, pt)).imag());
			chmin(low, R(h));
		}

		if(eq(up.real(), 0)) {
			high = h;
		} else {
			high = min(R(h), crosspoint(rightside, Line(up, pt)).imag());
			chmax(high, R(0));
		}

		if(cnt == 11 && low > high) {
			debug(low, high);
			debug(y, dn, up);
		}

		return high - low;
		// return max(high - low, R(0));
	};

	R ans = 0;
	rep(i, int(ys.size() - 1)) {
		R y_min = ys[i], y_max = ys[i + 1];
		if(eq(y_min, y_max)) continue;

		R mid = y_min + y_max;
		mid /= 2;

		int lb, ub;

		V<pair<R, int>> radians;
		rep(j, n2) {
			auto &p = ps[j];

			R deg;
			if(eq(p.real(), 0)) {
				deg = ((p.imag() < mid) ? -PI : PI);
			} else {
				deg = atan((p.imag() - mid) / p.real());
			}

			radians.emplace_back(deg, j);
		}

		sort(all(radians));

		lb = radians[n - 1].second;
		ub = radians[n].second;

		R res = kukan(y_min, ps[lb], ps[ub]);
		res += kukan(y_max, ps[lb], ps[ub]);
		res /= 2;
		res *= (y_max - y_min);

		ans += res;
	}

	cout << ans / h / h << dl;
	return;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int cnt = 0;
	while(1) {
		cnt++;
		solve(cnt);
	}

	return 0;
}
accuracy: 1
time_ms: 1680
memory_kb: 3924
final_rank: 13

code_snippet: /*	author:  Kite_kuma
	created: 2021.08.18 20:59:03 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region geometry

using Real = long double;
using R = Real;
using Point = std::complex<Real>;
using Vec = Point;
const Real EPS = 1e-10, PI = acos(-1);

inline bool eq(const Real &a, const Real &b) { return fabs(b - a) < EPS; }
inline bool eq(const Point &a, const Point &b) { return fabs(b - a) < EPS; }
/*
	-1: a < b
	0 : a == b
	1 : a > b
*/
inline int compare(const Real &a, const Real &b) { return eq(a, b) ? 0 : a < b ? -1 : 1; }

namespace std {
const Point operator*(const Point &p, const Real &d) { return Point(real(p) * d, imag(p) * d); }
}  // namespace std

std::istream &operator>>(std::istream &is, Point &p) {
	Real a, b;
	is >> a >> b;
	p = Point(a, b);
	return is;
}
std::ostream &operator<<(std::ostream &os, Point &p) { return os << std::fixed << std::setprecision(10) << p.real() << " " << p.imag(); }

// rotate point 'p' for counter clockwise direction
const Point rotate(const Real &theta, const Point &p) {
	return Point(cos(theta) * p.real() - sin(theta) * p.imag(), sin(theta) * p.real() + cos(theta) * p.imag());
}

const Real radian_to_degree(const Real &r) { return (r * 180.0 / PI); }

const Real degree_to_radian(const Real &d) { return (d * PI / 180.0); }

// get angle a-b-c (<pi)
const Real get_angle(const Point &a, const Point &b, const Point &c) {
	const Point v(a - b), w(c - b);
	Real theta = fabs(atan2(w.imag(), w.real()) - atan2(v.imag(), v.real()));
	return std::min(theta, 2 * PI - theta);
}

namespace std {
bool operator<(const Point &a, const Point &b) { return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag(); }
}  // namespace std

struct Line {
	Point a, b;

	Line() = default;

	Line(Point a, Point b) : a(a), b(b) {}

	Line(Real A, Real B, Real C)  // Ax + By = C
	{
		if(eq(A, 0))
			a = Point(0, C / B), b = Point(1, C / B);
		else if(eq(B, 0))
			b = Point(C / A, 0), b = Point(C / A, 1);
		else
			a = Point(0, C / B), b = Point(C / A, 0);
	}

	friend std::ostream &operator<<(std::ostream &os, Line &p) { return os << p.a << " -- " << p.b; }

	friend std::istream &operator>>(std::istream &is, Line &a) { return is >> a.a >> a.b; }
};

struct Segment : Line {
	Segment() = default;

	Segment(Point a, Point b) : Line(a, b) {}
};

struct Circle {
	Point p;
	Real r;

	Circle() = default;

	Circle(Point p, Real r) : p(p), r(r) {}
};

using Points = std::vector<Point>;
using Polygon = std::vector<Point>;
using Segments = std::vector<Segment>;
using Lines = std::vector<Line>;
using Circles = std::vector<Circle>;

const Real cross(const Point &a, const Point &b) { return real(a) * imag(b) - imag(a) * real(b); }
const Real dot(const Point &a, const Point &b) { return real(a) * real(b) + imag(a) * imag(b); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C
const int ccw(const Point &a, Point b, Point c) {
	b = b - a, c = c - a;
	if(cross(b, c) > EPS) return +1;		// "COUNTER_CLOCKWISE"
	if(cross(b, c) < -EPS) return -1;		// "CLOCKWISE"
	if(dot(b, c) < -EPS) return +2;			// "ONLINE_BACK"
	if(norm(b) + EPS < norm(c)) return -2;	// "ONLINE_FRONT"
	return 0;								// "ON_SEGMENT"
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool parallel(const Line &a, const Line &b) { return eq(cross(a.b - a.a, b.b - b.a), 0.0); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool orthogonal(const Line &a, const Line &b) { return eq(dot(a.a - a.b, b.a - b.b), 0.0); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A
Point projection(const Line &l, const Point &p) {
	double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + (l.a - l.b) * t;
}

Point projection(const Segment &l, const Point &p) {
	double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + (l.a - l.b) * t;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B
Point reflection(const Line &l, const Point &p) { return projection(l, p) * 2.0 - p; }

int intersect(const Line &l, const Point &p) { return int(abs(ccw(l.a, l.b, p)) != 1); }

int intersect(const Line &l, const Line &m) {
	if(intersect(l, m.a) && intersect(l, m.b)) return -1;
	return int(abs(cross(l.b - l.a, m.b - m.a)) > EPS);
}

int intersect(const Segment &s, const Point &p) { return int(ccw(s.a, s.b, p) == 0); }

int intersect(const Line &l, const Segment &s) {
	if(intersect(l, s.a) && intersect(l, s.b)) return -1;
	return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < EPS;
}

Real distance(const Line &l, const Point &p);

int intersect(const Circle &c, const Line &l) {
	Real d = c.r - distance(l, c.p);
	return fabs(d) < EPS ? 1 : d > 0. ? 2 : 0;
}

int intersect(const Circle &c, const Point &p) { return int(abs(abs(p - c.p) - c.r) < EPS); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
int intersect(const Segment &s, const Segment &t) {
	if(eq(s.a, s.b)) return intersect(t, s.a);
	if(intersect(Line(s), t.a) && intersect(Line(s), t.b) &&
	   std::max(std::min(s.a, s.b), std::min(t.a, t.b)) < std::min(std::max(s.a, s.b), std::max(t.a, t.b)))
		return -1;
	return int(ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0);
}

int intersect(const Circle &c, const Segment &l) {
	const Point h = projection(l, c.p);
	if(norm(h - c.p) - c.r * c.r > EPS) return 0;
	auto d1 = abs(c.p - l.a), d2 = abs(c.p - l.b);
	if(compare(d1, c.r) == -1 && compare(d2, c.r) == -1) return 0;
	if(d1 < c.r - EPS && d2 > c.r - EPS || d1 > c.r - EPS && d2 < c.r - EPS) return 1;
	return dot(l.a - h, l.b - h) < 0 ? 2 : 0;
}

Real distance(const Point &a, const Point &b);

int number_of_common_tangents(const Circle &c1, const Circle &c2) {
	Real r1 = std::min(c1.r, c2.r), r2 = std::max(c1.r, c2.r), d = distance(c1.p, c2.p);
	int com = compare(r1 + r2, d);
	return com == 1 ? compare(d + r1, r2) + 1 : 3 - com;
	// if(c1.r < c2.r) swap(c1, c2);
	// Real d = abs(c1.p - c2.p);
	// if(compare(c1.r + c2.r, d) == -1) return 4;
	// if(eq(c1.r + c2.r, d)) return 3;
	// if(compare(c1.r - c2.r, d) == -1) return 2;
	// return int(eq(c1.r - c2.r, d));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A&lang=jp
int intersect(const Circle &c1, const Circle &c2) { return 2 - abs(2 - number_of_common_tangents(c1, c2)); }

Real distance(const Point &a, const Point &b) { return abs(a - b); }

Real distance(const Line &l, const Point &p) { return abs(p - projection(l, p)); }

Real distance(const Line &l, const Line &m) { return intersect(l, m) ? 0 : distance(l, m.a); }

Real distance(const Segment &s, const Point &p) {
	Point r = projection(s, p);
	return intersect(s, r) ? distance(r, p) : std::min(abs(s.a - p), abs(s.b - p));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_D
Real distance(const Segment &a, const Segment &b) {
	if(intersect(a, b)) return 0;
	return std::min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}

Real distance(const Line &l, const Segment &s) {
	if(intersect(l, s)) return 0;
	return std::min(distance(l, s.a), distance(l, s.b));
}

Point crosspoint(const Line &l, const Line &m) {
	Real A = cross(l.b - l.a, m.b - m.a);
	Real B = cross(l.b - l.a, l.b - m.a);
	if(eq(abs(A), 0.0) && eq(abs(B), 0.0)) return m.a;
	return m.a + (m.b - m.a) * B / A;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_C
Point crosspoint(const Segment &l, const Segment &m) { return crosspoint(Line(l), Line(m)); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_D
std::pair<Point, Point> crosspoint(const Circle &c, const Line l) {
	Point pr = projection(l, c.p);
	if(eq(distance(l, c.p), c.r)) return {pr, pr};
	Vec v = (l.b - l.a) / abs(l.b - l.a) * sqrt(c.r * c.r - norm(pr - c.p));
	return make_pair(pr - v, pr + v);
	// Vec e = (l.b - l.a) / abs(l.b - l.a);
	// double base = sqrt(c.r * c.r - norm(pr - c.p));
	// return {pr - e * base, pr + e * base};
}

std::pair<Point, Point> crosspoint(const Circle &c, const Segment &l) {
	if(intersect(c, l) == 2) return crosspoint(c, Line(l.a, l.b));
	auto ret = crosspoint(c, Line(l.a, l.b));
	if(dot(l.a - ret.first, l.b - ret.first) < EPS)
		ret.second = ret.first;
	else
		ret.first = ret.second;
	return ret;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_E
std::pair<Point, Point> crosspoint(const Circle &c1, const Circle &c2) {
	Real d = abs(c1.p - c2.p);
	Real a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));  // cosine theorem
	Real t = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	Point p1 = c1.p + Point(cos(t + a) * c1.r, sin(t + a) * c1.r);
	Point p2 = c1.p + Point(cos(t - a) * c1.r, sin(t - a) * c1.r);
	return make_pair(p1, p2);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_F
// "点 p を通る円 c の接線"の接点2つ
std::pair<Point, Point> tangent(const Circle &c1, const Point &p2) {
	return crosspoint(c1, Circle(p2, sqrt(norm(c1.p - p2) - c1.r * c1.r)));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_G
// 円 c1, c2 の共通接線
Lines tangent(Circle c1, Circle c2) {
	Lines ret;
	if(c1.r < c2.r) std::swap(c1, c2);
	Real g = norm(c1.p - c2.p);
	if(eq(g, 0)) return ret;
	Vec u = (c2.p - c1.p) / Real(sqrt(g));
	Vec v = rotate(PI * 0.5, u);
	for(int s : {-1, 1}) {
		Real h = (c1.r + s * c2.r) / sqrt(g);
		if(eq(1 - h * h, 0)) {
			ret.emplace_back(c1.p + u * c1.r, c1.p + (u + v) * c1.r);
		} else if(1 - h * h > 0) {
			Point uu = u * h, vv = v * sqrt(1 - h * h);
			ret.emplace_back(c1.p + (uu + vv) * c1.r, c2.p - (uu + vv) * c2.r * s);
			ret.emplace_back(c1.p + (uu - vv) * c1.r, c2.p - (uu - vv) * c2.r * s);
		}
	}
	return ret;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_B
bool is_convex(const Polygon &p, bool pi_is_ok = false) {
	int n = p.size();
	if(pi_is_ok) {
		for(int i = 0; i < n; i++)
			if(ccw(p[i], p[(i + 1) % n], p[(i + 2) % n]) == -1) return false;
	} else {
		for(int i = 0; i < n; i++)
			if(ccw(p[i], p[(i + 1) % n], p[(i + 2) % n]) != 1) return false;
	}
	return true;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A
Polygon convex_hull(Polygon &p, bool pi_is_ok = false) {
	int n = (int)p.size(), k = 0;
	if(n <= 2) return p;
	sort(p.begin(), p.end());
	Points ch(2 * n);
	if(pi_is_ok) {
		for(int i = 0; i < n; ch[k++] = p[i++])
			while(k >= 2 && ccw(ch[k - 2], ch[k - 1], p[i]) == -1) --k;
		for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--])
			while(k >= t && ccw(ch[k - 2], ch[k - 1], p[i]) == -1) --k;
	} else {
		for(int i = 0; i < n; ch[k++] = p[i++])
			while(k >= 2 && ccw(ch[k - 2], ch[k - 1], p[i]) != 1) --k;
		for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--])
			while(k >= t && ccw(ch[k - 2], ch[k - 1], p[i]) != 1) --k;
	}
	ch.resize(k - 1);
	return ch;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
enum { OUT, ON, IN };
int contains(const Polygon &Q, const Point &p) {
	bool in = false;
	const Real p_y = p.imag();
	for(int i = 0; i < Q.size(); i++) {
		Point a = Q[i], b = Q[(i + 1) % Q.size()];
		if(ccw(a, b, p) == 0) return ON;
		if(a.imag() > b.imag()) swap(a, b);
		if(a.imag() <= p_y && p_y < b.imag() && cross(a - p, b - p) < 0) in = !in;
	}
	return in ? IN : OUT;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1033
// 線分の重複除去
void merge_segments(std::vector<Segment> &segs) {
	auto merge_if_able = [](Segment &s1, const Segment &s2) {
		if(abs(cross(s1.b - s1.a, s2.b - s2.a)) > EPS) return false;
		if(ccw(s1.a, s2.a, s1.b) == 1 || ccw(s1.a, s2.a, s1.b) == -1) return false;
		if(ccw(s1.a, s1.b, s2.a) == -2 || ccw(s2.a, s2.b, s1.a) == -2) return false;
		s1 = Segment(min(s1.a, s2.a), max(s1.b, s2.b));
		return true;
	};

	for(int i = 0; i < segs.size(); i++) {
		if(segs[i].b < segs[i].a) swap(segs[i].a, segs[i].b);
	}
	for(int i = 0; i < segs.size(); i++) {
		for(int j = i + 1; j < segs.size(); j++) {
			if(merge_if_able(segs[i], segs[j])) {
				segs[j--] = segs.back(), segs.pop_back();
			}
		}
	}
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1033
// 線分アレンジメント
// 任意の2線分の交点を頂点としたグラフを構築する
std::vector<std::vector<int>> segment_arrangement(std::vector<Segment> &segs, std::vector<Point> &ps) {
	std::vector<std::vector<int>> g;
	int N = (int)segs.size();
	for(int i = 0; i < N; i++) {
		ps.emplace_back(segs[i].a);
		ps.emplace_back(segs[i].b);
		for(int j = i + 1; j < N; j++) {
			const Point p1 = segs[i].b - segs[i].a;
			const Point p2 = segs[j].b - segs[j].a;
			if(eq(cross(p1, p2), 0)) continue;	// " == 0" となっていたのを訂正
			if(intersect(segs[i], segs[j])) {
				ps.emplace_back(crosspoint(segs[i], segs[j]));
			}
		}
	}
	sort(begin(ps), end(ps));
	ps.erase(unique(begin(ps), end(ps)), end(ps));	// 誤差?

	int M = (int)ps.size();
	g.resize(M);
	for(int i = 0; i < N; i++) {
		std::vector<int> vec;
		for(int j = 0; j < M; j++) {
			if(intersect(segs[i], ps[j])) {
				vec.emplace_back(j);
			}
		}
		for(int j = 1; j < vec.size(); j++) {
			g[vec[j - 1]].push_back(vec[j]);
			g[vec[j]].push_back(vec[j - 1]);
		}
	}
	return (g);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_C
// 凸多角形の切断
// 直線 l.a-l.b で切断しその左側にできる凸多角形を返す
Polygon convex_cut(const Polygon &U, Line l) {
	Polygon ret;
	for(int i = 0; i < U.size(); i++) {
		Point now = U[i], nxt = U[(i + 1) % U.size()];
		if(ccw(l.a, l.b, now) != -1) ret.push_back(now);
		if(ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) == -1) ret.push_back(crosspoint(Line(now, nxt), l));
	}
	return ret;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_A
// 多角形の面積
Real area(const Polygon &p) {
	Real A = 0;
	for(int i = 0; i < p.size(); ++i) {
		A += cross(p[i], p[(i + 1) % p.size()]);
	}
	return A * 0.5;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_H
// 円と多角形の共通部分の面積
Real area(const Polygon &p, const Circle &c) {
	if(p.size() < 3) return 0.0;
	auto cross_area = [&c](auto cross_area, const Point &a, const Point &b) -> Real {
		Point va = c.p - a, vb = c.p - b;
		Real f = cross(va, vb), ret = 0.0;
		if(eq(f, 0.0)) return ret;
		if(std::max(abs(va), abs(vb)) < c.r + EPS) return f;
		if(distance(Segment(a, b), c.p) > c.r - EPS) return c.r * c.r * arg(vb * conj(va));
		auto u = crosspoint(c, Segment(a, b));
		std::vector<Point> tot{a, u.first, u.second, b};
		for(int i = 0; i + 1 < tot.size(); i++) ret += cross_area(cross_area, tot[i], tot[i + 1]);
		return ret;
	};
	Real A = 0;
	for(int i = 0; i < p.size(); i++) {
		A += cross_area(cross_area, p[i], p[(i + 1) % p.size()]);
	}
	return A * 0.5;
}

#pragma endregion

void solve() {
	int w, h, n;
	cin >> w >> h >> n;

	if(w + h + n == 0) exit(0);
	int n2 = n + n;

	Points ps(n2);
	rep(i, n2) { cin >> ps[i]; }

	Points ps_all = ps;
	ps_all.emplace_back(0, 0);
	ps_all.emplace_back(0, h);
	ps_all.emplace_back(w, 0);
	ps_all.emplace_back(w, h);

	V<R> ys;

	Line leftside(Point(0, 0), Point(0, 1));
	Line rightside(Point(w, 0), Point(w, 1));

	rep(i, int(ps_all.size())) {
		rep(j, i + 1, int(ps_all.size())) {
			Point &p = ps_all[i], &r = ps_all[j];
			// if(eq(p.real(), r.real())) continue;
			Line ln(p, r);
			if(intersect(ln, leftside) != 1) continue;
			Real y = crosspoint(leftside, ln).imag();
			if(isnan(y)) continue;
			if(-EPS <= y && y <= h + EPS) ys.push_back(y);
		}
		ys.push_back(ps_all[i].imag());
	}
	sort(all(ys));

	debug(ys);

	auto kukan = [&](R y, Point &dn, Point &up) {
		Point pt(0, y);
		R low, high;
		if(eq(dn.real(), 0)) {
			low = 0;
		} else {
			low = max(R(0), crosspoint(rightside, Line(dn, pt)).imag());
		}

		if(eq(up.real(), 0)) {
			high = h;
		} else {
			high = min(R(h), crosspoint(rightside, Line(up, pt)).imag());
		}
		return max(high - low, R(0));
	};

	R ans = 0;
	rep(i, int(ys.size() - 1)) {
		R y_min = ys[i], y_max = ys[i + 1];
		if(eq(y_min, y_max)) continue;
		debug(y_min, y_max);
		R mid = y_min + y_max;
		mid /= 2;

		int lb, ub;

		V<pair<R, int>> radians;
		rep(j, n2) {
			auto &p = ps[j];

			R deg;
			if(eq(p.real(), 0)) {
				deg = ((p.imag() < mid) ? -PI : PI);
			} else {
				deg = atan((p.imag() - mid) / p.real());
			}

			radians.emplace_back(deg, j);
		}

		sort(all(radians));

		lb = radians[n - 1].second;
		ub = radians[n].second;

		debug(lb, ub);
		debug(ps[lb], ps[ub]);

		R res = kukan(y_min, ps[lb], ps[ub]);
		res += kukan(y_max, ps[lb], ps[ub]);
		res /= 2;
		res *= (y_max - y_min);

		ans += res;

		debug(res, ans);
	}

	cout << ans / h / h << dl;
	return;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	while(1) solve();

	return 0;
}
accuracy: 1
time_ms: 1630
memory_kb: 3928
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=205,INF=1<<30;
//#define double long double
//幾何ライブラリ

const double eps=1e-10;
const double pi=acos((double)-1.0L);
#define equals(a,b) (fabs((a)-(b))<eps)

double torad(double deg) {return (double)(deg)*pi/180.0;}
double todeg(double ang) {return ang*180.0/pi;}

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 a){return Point(a*x,a*y);}
    Point operator / (double a){return Point(x/a,y/a);}
    
    double abs(){return sqrt(norm());}
    double norm(){return x*x+y*y;}
    
    bool operator < (const Point &p)const{
        return x+eps<p.x||(equals(x,p.x)&&y+eps<p.y);
    }
    
    bool operator == (const Point &p)const{
        return fabs(x-p.x)<eps&&fabs(y-p.y)<eps;
    }
};

typedef Point Vector;

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

struct Segment{
    Point p1,p2;
};

bool isOrthogonal(Vector a,Vector b){
    return equals(dot(a,b),0.0);
}

bool isOrthogonal(Point a1,Point a2,Point b1,Point b2){
    return isOrthogonal(a1-a2,b1-b2);
}

bool isOrthogonal(Segment s1,Segment s2){
    return equals(dot(s1.p2-s1.p1,s2.p2-s2.p1),0.0);
}

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

bool isParallel(Point a1,Point a2,Point b1,Point b2){
    return isParallel(a1-a2,b1-b2);
}

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

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

Point reflect(Segment s,Point p){
    return p+(project(s,p)-p)*2.0;
}

Point turn(Point p,Point c,double pi){
    double q=atan2(p.y-c.y,p.x-c.x);
    q+=pi;
    p=c+Point{cos(q)*abs(p-c),sin(q)*abs(p-c)};
    
    return p;
}
//pをcを中心としてpi回転させる(1周で2π)
//p=cのときnan

//p0,p1,p2の順に見たときどうなるか？

static const int counter_clockwise=1;
static const int clockwise=-1;
static const int online_back=2;
static const int online_front=-2;
static const int on_segment=0;

int ccw(Point p0,Point p1,Point p2){
    Vector a=p1-p0;
    Vector b=p2-p0;
    
    if(cross(a,b)>eps) return counter_clockwise;
    if(cross(a,b)<-eps) return clockwise;
    if(dot(a,b)<-eps) return online_back;
    if(a.norm()<b.norm()) return online_front;
    
    return on_segment;
}

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

bool overlap(Segment s1,Segment s2){
    int a=ccw(s1.p1,s1.p2,s2.p1),b=ccw(s1.p1,s1.p2,s2.p2);
    if(a&1||b&1) return 0;
    if(a==2){
        if(b==-2||(b==0&&!(s2.p2==s1.p1))) return 1;
        else return 0;
    }
    if(a==-2){
        if(b==2||(b==0&&!(s2.p2==s1.p2))) return 1;
        else return 0;
    }
    if(a==0){
        if(s1.p1==s2.p1){
            if(b!=2) return 1;
            else return 0;
        }
        else if(s1.p2==s2.p1){
            if(b!=-2) return 1;
            else return 0;
        }
        else return 1;
    }
    return 0;
}
//s1とs2の共通の線分(長さ0より大きい)があるかどうか

typedef Segment Line;

double getDistance(Point a,Point b){
    return abs(a-b);
}

double getDistanceLP(Line l,Point p){
    return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

double getDistanceSP(Segment s,Point p){
    if(dot(s.p2-s.p1,p-s.p1)<0.0) return abs(p-s.p1);
    if(dot(s.p1-s.p2,p-s.p2)<0.0) return abs(p-s.p2);
    return getDistanceLP(s,p);
}

double getDistance(Segment s1,Segment s2){
    if(intersect(s1,s2)) return 0.0;
    return min({getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2),getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2)});
}

Point getCrossPointS(Segment s1,Segment s2){
    //if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
    Vector base=s2.p2-s2.p1;
    double d1=abs(cross(base,s1.p1-s2.p1));
    double d2=abs(cross(base,s1.p2-s2.p1));
    double t=d1/(d1+d2);
    return s1.p1+(s1.p2-s1.p1)*t;
}//同じ時壊れます

Point getCrossPointL(Line l1,Line l2){
    //if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
    
    Vector v1=l1.p2-l1.p1,v2=l2.p2-l2.p1;
    
    return l1.p1+v1*cross(v2,l2.p1-l1.p1)/cross(v2,v1);
}

Segment ParallelSegment(Segment s,double d){
    Vector v={-(s.p2-s.p1).y,(s.p2-s.p1).x};
    v=v/abs(v);
    
    s.p1=s.p1+v*d;
    s.p2=s.p2+v*d;
    
    return s;
}

Point naisin(Point p1,Point p2,Point p3){
    if(p1==p2&&p2==p3&&p3==p1) return p1;
    
    return (p1*abs(p2-p3)+p2*abs(p1-p3)+p3*abs(p1-p2))/(abs(p2-p3)+abs(p1-p3)+abs(p1-p2));
}

Point naisin(Line l1,Line l2,Line l3){
    //平行でない前提
    
    Point p1=getCrossPointL(l1,l2),p2=getCrossPointL(l1,l3),p3=getCrossPointL(l2,l3);
    return naisin(p1,p2,p3);
}

//ネットの適当を書いたのであってるか全く知りません→あってそう

class Circle{
public:
    Point c;
    double r;
    Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

Point CircleCenter(Point a,Point b,Point c){
    Point u=a-b,v=a-c;
    double m1=(norm(a)-norm(b))/2.0,m2=(norm(a)-norm(c))/2.0;
    
    Point res;
    if(cross(u,v)==0.0){
        res.x=1e9;
        res.y=1e9;
        
        return res;
    }
    res.x=(m1*v.y-m2*u.y)/cross(u,v);
    res.y=(m1*v.x-m2*u.x)/cross(v,u);
    
    return res;
}
//3点を通る円の中心を返す

//交わる 0
// c1がc2のinside 1
// c1がc2のoutside 2
// 交わらない 3

int not_intersect(Circle c1,Circle c2){
    double d=getDistance(c1.c,c2.c);
    double r1=c1.r,r2=c2.r;
    if(r1<r2){
        if(d<(r2-r1)) return 1;
    }
    if(r1>r2){
        if(d<(r1-r2)) return 2;
    }
    if(d<=r1+r2) return 0;
    else return 3;
}

pair<Point,Point> segCrossPpoints(Circle c,Line l){
    //assert(intersect(c,l));
    Vector pr=project(l,c.c);
    Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
    double base=sqrt(c.r*c.r-norm(pr-c.c));
    return make_pair(pr+e*base,pr-e*base);
}

double arg(Vector p){return atan2(p.y,p.x);}
Vector polar(double a,double r){return Point(cos(r)*a,sin(r)*a);}

//inside(outside)

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
    //assert(intersect(c1,c2));
    double d=abs(c1.c-c2.c);
    double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
    double t=arg(c2.c-c1.c);
    return make_pair(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

vector<Line> Commontangent(Circle c1,Circle c2){
    vector<Line> res;
    Point p=c2.c-c1.c;
    
    if(abs(p)>=(c1.r+c2.r)){
        Point a,b;
        a.x=c1.r*(p.x*(c1.r+c2.r)+p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        a.y=c1.r*(p.y*(c1.r+c2.r)-p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        
        b.x=c1.r*(p.x*(c1.r+c2.r)-p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        b.y=c1.r*(p.y*(c1.r+c2.r)+p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        
        res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
        if(!(a==b)){
            res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
        }
    }
    
    if(abs(p)>=abs(c1.r-c2.r)){
        Point a,b;
        a.x=c1.r*(p.x*(c1.r-c2.r)+p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        a.y=c1.r*(p.y*(c1.r-c2.r)-p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        
        b.x=c1.r*(p.x*(c1.r-c2.r)-p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        b.y=c1.r*(p.y*(c1.r-c2.r)+p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        
        res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
        if(!(a==b)){
            res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
        }
    }
    
    return res;
}

typedef vector<Point> Polygon;

/*
 IN 2
 ON 1
 OUT 0
 */

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

Polygon andrewScan(Polygon s,bool ok){
    Polygon u,l;
    sort(all(s));
    
    if(int(s.size())<3) return s;
    int n=int(s.size());
    
    u.push_back(s[0]);
    u.push_back(s[1]);
    
    l.push_back(s[n-1]);
    l.push_back(s[n-2]);
    
    if(ok){
        for(int i=2;i<n;i++){
            for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])==counter_clockwise;j--){
                u.pop_back();
            }
            u.push_back(s[i]);
        }
        
        for(int i=int(s.size())-3;i>=0;i--){
            for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])==counter_clockwise;j--){
                l.pop_back();
            }
            l.push_back(s[i]);
        }
    }
    
    if(!ok){
        for(int i=2;i<n;i++){
            for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])!=clockwise;j--){
                u.pop_back();
            }
            u.push_back(s[i]);
        }
        
        for(int i=int(s.size())-3;i>=0;i--){
            for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])!=clockwise;j--){
                l.pop_back();
            }
            l.push_back(s[i]);
        }
    }
    
    reverse(all(l));
    
    for(int i=int(u.size())-2;i>=1;i--) l.push_back(u[i]);
    
    return l;
}//ok==1なら辺の上も含める

Polygon convex_cut(const Polygon& P, const Line& l) {
    Polygon Q;
    for(int i=0;i<si(P);i++){
        Point A=P[i],B=P[(i+1)%si(P)];
        if(ccw(l.p1,l.p2,A)!=-1)Q.push_back(A);
        if(ccw(l.p1,l.p2,A)*ccw(l.p1,l.p2,B)<0) Q.push_back(getCrossPointL(Line{A,B},l));
    }
    return Q;
}

double area(Point a,Point b,Point c){
    b=b-a;
    c=c-a;
    return abs(b.x*c.y-b.y*c.x)/2.0;
}

double area(Polygon &P){
    if(si(P)==0) return 0.0;
    double res=0;
    Point c={0.0,0.0};
    for(int i=0;i<si(P);i++){
        c=c+P[i];
    }
    c=c/si(P);
    
    for(int i=0;i<si(P);i++){
        res+=area(c,P[i],P[(i+1)%si(P)]);
    }
    
    return res;
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        int H,W,N;cin>>W>>H>>N;
        if(H==0) break;
        vector<Point> P(2*N);
        for(int i=0;i<2*N;i++) cin>>P[i].x>>P[i].y;
        sort(all(P));
        if(P.back().x==0){
            double ku=P[N].y-P[N-1].y;
            cout<<fixed<<setprecision(25)<<(ku/H)<<"\n";
            continue;
        }
        P.push_back({(double)W,0});
        P.push_back({(double)W,(double)H});
        Line l={{0,0},{0,(double)H}};
        vector<Point> Q;
        Q.push_back({0,0});
        Q.push_back({0,(double)H});
        for(int i=0;i<2*N;i++){
            for(int j=0;j<2*N+2;j++){
                Point a=P[i],b=P[j];
                if(a==b) continue;
                Line l2={a,b};
                if(isParallel(l,l2)) continue;
                Point c=getCrossPointL(l,l2);
                if(c.y<0||c.y>H) continue;
                Q.push_back(c);
            }
        }
        sort(all(Q));
        Q.erase(unique(all(Q)),Q.end());
        
        //for(auto p:Q) cout<<p.x<<" "<<p.y<<endl;
        
        double ans=0;
        
        for(int q=0;q+1<si(Q);q++){
            Point m=(Q[q]+Q[q+1])/2;
            double u,d,left,right;
            left=0;right=H;
            for(int t=0;t<30;t++){
                double mid=(left+right)/2;
                Line l={m,{(double)W,mid}};
                int cnt=0;
                for(int i=0;i<2*N;i++){
                    int cc=ccw(l.p1,l.p2,P[i]);
                    if(cc!=1) cnt++;
                }
                if(cnt<N) left=mid;
                else right=mid;
            }
            d=left;
            left=0;right=H;
            for(int t=0;t<30;t++){
                double mid=(left+right)/2;
                Line l={m,{(double)W,mid}};
                int cnt=0;
                for(int i=0;i<2*N;i++){
                    int cc=ccw(l.p1,l.p2,P[i]);
                    if(cc!=1) cnt++;
                }
                if(cnt>N) right=mid;
                else left=mid;
            }
            u=right;
            
            //cout<<d<<" "<<u<<endl;
            
            ans+=(Q[q+1].y-Q[q].y)*(u-d);
        }
        
        ans/=H;
        ans/=H;
        
        cout<<fixed<<setprecision(25)<<ans<<"\n";
    }
}
accuracy: 1
time_ms: 6400
memory_kb: 4096
final_rank: 20

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

static const double EPS = 1e-9;

int main() {
  while (true) {
    int w, h, n;
    cin >> w >> h >> n;
    if (w == 0) return 0;

    vector<double> x(2 * n), y(2 * n);
    for (int i = 0; i < 2 * n; i++) cin >> x.at(i) >> y.at(i);
    x.emplace_back((double) w);
    x.emplace_back((double) w);
    x.emplace_back(0.0);
    x.emplace_back(0.0);
    y.emplace_back(0.0);
    y.emplace_back((double) h);
    y.emplace_back(0.0);
    y.emplace_back((double) h);

    vector<double> z;
    z.emplace_back(0.0);
    z.emplace_back((double) h);

    for (int i = 0; i < 2 * n + 4; i++) {
      for (int j = i + 1; j < 2 * n + 4; j++) {
	if (abs(x[i] - x[j]) < EPS) continue;
	double m = (y[j] - y[i]) / (x[j] - x[i]);
	double keep = y[i] - m * x[i];
	if (keep < -EPS || keep > h + EPS) continue;
	int count = 0, count2 = 0;
	for (int k = 0; k < 2 * n; k++) {
	  double keep1 = y[k], keep2 = keep + m * x[k];
	  if (keep1 > keep2 + EPS) count++;
	  else if (keep1 > keep2 - EPS) count2++;
	}
	if (count + count2 >= n && count <= n) z.emplace_back(keep);
      }
    }

    sort(z.begin(), z.end());
    z.erase(unique(z.begin(), z.end()), z.end());

    double area = 0.0;
    for (int i = 1; i < z.size(); i++) {
      if (abs(z[i] - z[i - 1]) <= EPS) continue;
      double midp = (z[i] + z[i - 1]) / 2.0;
      double high = h, low = 0;
      for (int cycle = 0; cycle < 150; cycle++) {
	double mid = (high + low) / 2.0;
	double midm = (mid - midp) / (double) w;
	int up = 0;
	for (int k = 0; k < 2 * n; k++) {
	  if (y[k] + EPS >= midp + midm * x[k]) up++;
	}
	if (up >= n) low = mid;
	else high = mid;
      }
      double upperp = high;
      high = h, low = 0;
      for (int cycle = 0; cycle < 150; cycle++) {
	double mid = (high + low) / 2.0;
	double midm = (mid - midp) / (double) w;
	int up = 0;
	for (int k = 0; k < 2 * n; k++) {
	  if (y[k] + EPS >= midp + midm * x[k]) up++;
	}
	if (up > n) low = mid;
	else high = mid;
      }
      double lowerp = low;
      area += max(0.0, (upperp - lowerp) * (z[i] - z[i - 1]));
    }

    cout << fixed << setprecision(10) << area / (double) (h * h) << '\n';
  }
}
accuracy: 1
time_ms: 270
memory_kb: 3496
final_rank: 2

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

static const double EPS = 1e-9;

int main() {
  while (true) {
    int w, h, n;
    cin >> w >> h >> n;
    if (w == 0) return 0;

    vector<double> x(2 * n), y(2 * n);
    for (int i = 0; i < 2 * n; i++) cin >> x.at(i) >> y.at(i);
    x.emplace_back((double) w);
    x.emplace_back((double) w);
    x.emplace_back(0.0);
    x.emplace_back(0.0);
    y.emplace_back(0.0);
    y.emplace_back((double) h);
    y.emplace_back(0.0);
    y.emplace_back((double) h);

    vector<double> z;
    z.emplace_back(0.0);
    z.emplace_back((double) h);

    for (int i = 0; i < 2 * n + 4; i++) {
      for (int j = i + 1; j < 2 * n + 4; j++) {
	if (abs(x[i] - x[j]) < EPS) continue;
	double m = (y[j] - y[i]) / (x[j] - x[i]);
	double keep = y[i] - m * x[i];
	if (keep < -EPS || keep > h + EPS) continue;
	int count = 0, count2 = 0;
	for (int k = 0; k < 2 * n; k++) {
	  double keep1 = y[k], keep2 = keep + m * x[k];
	  if (keep1 > keep2 + EPS) count++;
	  else if (keep1 > keep2 - EPS) count2++;
	}
	if (count + count2 >= n && count <= n) z.emplace_back(keep);
      }
    }

    sort(z.begin(), z.end());
    z.erase(unique(z.begin(), z.end()), z.end());

    double area = 0.0;
    for (int i = 1; i < z.size(); i++) {
      if (abs(z[i] - z[i - 1]) <= EPS) continue;
      double midp = (z[i] + z[i - 1]) / 2.0;
      double high = h, low = 0;
      for (int cycle = 0; cycle < 150; cycle++) {
	double mid = (high + low) / 2.0;
	double midm = (mid - midp) / (double) w;
	int up = 0;
	for (int k = 0; k < 2 * n; k++) {
	  if (y[k] + EPS >= midp + midm * x[k]) up++;
	}
	if (up >= n) low = mid;
	else high = mid;
      }
      double upperp = high;
      high = h, low = 0;
      for (int cycle = 0; cycle < 150; cycle++) {
	double mid = (high + low) / 2.0;
	double midm = (mid - midp) / (double) w;
	int up = 0;
	for (int k = 0; k < 2 * n; k++) {
	  if (y[k] + EPS >= midp + midm * x[k]) up++;
	}
	if (up > n) low = mid;
	else high = mid;
      }
      double lowerp = low;
      area += max(0.0, (upperp - lowerp) * (z[i] - z[i - 1]));
    }

    cout << fixed << setprecision(10) << area / (double) (h * h) << '\n';
  }
}
accuracy: 1
time_ms: 270
memory_kb: 3500
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
const double INF = 1000000000;
const double EPS = 0.000000001;
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): 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);
  }
};
double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
struct line{
  point A, B;
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
double area(double l, double r, double u, double d, double H){
  if (u < EPS){
    return 0;
  }
  if (d > H - EPS){
    return (r - l) * H;
  }
  if (d > 0){
    if (u < H){
      return (d + u) * (r - l) / 2;
    } else {
      double x = l + (H - d) / (u - d) * (r - l);
      return ((r - x) + (r - l)) * (H - d) / 2 + (r - l) * d;
    }
  } else {
    if (u < H){
      double x = l + (-d) / (u - d) * (r - l);
      return (r - x) * u / 2;
    } else {
      double x1 = l + (-d) / (u - d) * (r - l);
      double x2 = l + (H - d) / (u - d) * (r - l);
      return ((r - x2) + (r - x1)) * H / 2;
    }
  }
}
int main(){
  cout << fixed << setprecision(20);
  while (true){
    int W, H, N;
    cin >> W >> H >> N;
    if (W == 0 && H == 0 && N == 0){
      break;
    }
    vector<point> P(N * 2);
    for (int i = 0; i < N * 2; i++){
      cin >> P[i].x >> P[i].y;
    }
    vector<double> Y;
    Y.push_back(0);
    Y.push_back(H);
    for (int i = 0; i < N * 2; i++){
      if (P[i].x <= EPS){
        Y.push_back(P[i].y);
      } else {
        for (int j = i + 1; j < N * 2; j++){
          if (P[j].x > EPS && abs(P[i].x - P[j].x) > EPS){
            point Q = line_intersection(line(point(0, 0), point(0, H)), line(P[i], P[j]));
            if (0 <= Q.y && Q.y <= H){
              Y.push_back(Q.y);
            }
          }
        }
      }
    }
    sort(Y.begin(), Y.end());
    int M = Y.size();
    double ans = 0;
    for (int i = 0; i < M - 1; i++){
      vector<double> Y1(N * 2), Y2(N * 2);
      for (int j = 0; j < N * 2; j++){
        if (P[j].x <= EPS){
          if (P[j].y <= Y[i] + EPS){
            Y1[j] = -INF;
            Y2[j] = -INF;
          } else {
            Y1[j] = INF;
            Y2[j] = INF;
          }
        } else {
          point Q1 = line_intersection(line(point(W, 0), point(W, H)), line(point(0, Y[i]), P[j]));
          Y1[j] = Q1.y;
          point Q2 = line_intersection(line(point(W, 0), point(W, H)), line(point(0, Y[i + 1]), P[j]));
          Y2[j] = Q2.y;
        }
      }
      sort(Y1.begin(), Y1.end());
      sort(Y2.begin(), Y2.end());
      ans -= area(Y[i], Y[i + 1], Y1[N - 1], Y2[N - 1], H);
      ans += area(Y[i], Y[i + 1], Y1[N], Y2[N], H);
    }
    ans /= H * H;
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 670
memory_kb: 3240
final_rank: 1