Problem:
Problem H:
Inherit the Spheres
In the year 2xxx, an expedition team landing on a planet found strange objects made by an
ancient species living on that planet. They are transparent boxes containing opaque solid spheres
(Figure 1). There are also many lithographs which seem to contain positions and radiuses of
spheres.
Figure 1: A strange object
Initially their objective was unknown, but Professor Zambendorf found the cross section formed
by a horizontal plane plays an important role. For example, the cross section of an object
changes as in Figure 2 by sliding the plane from bottom to top.
Figure 2: Cross sections at different positions
He eventually found that some information is expressed by the transition of the number of
connected figures in the cross section, where each connected figure is a union of discs intersecting
or touching each other, and each disc is a cross section of the corresponding solid sphere. For
instance, in Figure 2, whose geometry is described in the first sample dataset later, the number
of connected figures changes as 0, 1, 2, 1, 2, 3, 2, 1, and 0, at
z
= 0.0000, 162.0000, 167.0000,
173.0004, 185.0000, 191.9996, 198.0000, 203.0000, and 205.0000, respectively. By assigning 1 for
increment and 0 for decrement, the transitions of this sequence can be expressed by an 8-bit
binary number 11011000.
For helping further analysis, write a program to determine the transitions when sliding the
horizontal plane from bottom (
z
= 0) to top (
z
= 36000).
Input
The input consists of a series of datasets. Each dataset begins with a line containing a positive
integer, which indicates the number of spheres
N
in the dataset. It is followed by
N
lines
describing the centers and radiuses of the spheres. Each of the
N
lines has four positive integers
X
i
,
Y
i
,
Z
i
, and
R
i
(
i
= 1, . . . ,
N
) describing the center and the radius of the
i
-th sphere,
respectively.
You may assume 1 ≤
N
≤ 100, 1 ≤
R
i
≤ 2000, 0 <
X
i
-
R
i
<
X
i
+
R
i
< 4000, 0 <
Y
i
-
R
i
<
Y
i
+
R
i
< 16000, and 0 <
Z
i
-
R
i
<
Z
i
+
R
i
< 36000. Each solid sphere is defined as the set of
all points (
x
,
y
,
z
) satisfying (
x
-
X
i
)
2
+ (
y
-
Y
i
)
2
+ (
z
-
Z
i
)
2
≤
R
i
2
.
A sphere may contain other spheres. No two spheres are mutually tangent. Every
Z
i
±
R
i
and
minimum/maximum
z
coordinates of a circle formed by the intersection of any two spheres differ
from each other by at least 0.01.
The end of the input is indicated by a line with one zero.
Output
For each dataset, your program should output two lines. The first line should contain an integer
M
indicating the number of transitions. The second line should contain an
M
-bit binary number
that expresses the transitions of the number of connected figures as specified above.
Sample Input
3
95 20 180 18
125 20 185 18
40 27 195 10
1
5 5 5 4
2
5 5 5 4
5 5 5 3
2
5 5 5 4
5 7 5 3
16
2338 3465 29034 710
1571 14389 25019 842
1706 8015 11324 1155
1899 4359 33815 888
2160 10364 20511 1264
2048 8835 23706 1906
2598 13041 23
...(truncated)

Submitted solutions:

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

class UnionFind {
public:
    UnionFind() = default;
    explicit UnionFind(int n) : data(n, -1) {}

    int find(int x) {
        if (data[x] < 0) return x;
        return data[x] = find(data[x]);
    }

    void unite(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) return;
        if (data[x] > data[y]) std::swap(x, y);
        data[x] += data[y];
        data[y] = x;
    }

    bool same(int x, int y) {
        return find(x) == find(y);
    }

    int size(int x) {
        return -data[find(x)];
    }

private:
    std::vector<int> data;
};

using T = double;
using Vec = std::complex<T>;

const T PI = std::acos(-1);

constexpr T eps = 1e-10;
inline bool eq(T a, T b) { return std::abs(a - b) <= eps; }
inline bool eq(Vec a, Vec b) { return std::abs(a - b) <= eps; }
inline bool lt(T a, T b) { return a < b - eps; }
inline bool leq(T a, T b) { return a <= b + eps; }

std::istream& operator>>(std::istream& is, Vec& p) {
    T x, y;
    is >> x >> y;
    p = {x, y};
    return is;
}

struct Line {
    Vec p1, p2;
    Line() = default;
    Line(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Segment {
    Vec p1, p2;
    Segment() = default;
    Segment(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Circle {
    Vec c;
    T r;
    Circle() = default;
    Circle(const Vec& c, T r) : c(c), r(r) {}
};

using Polygon = std::vector<Vec>;

T dot(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).real();
}

T cross(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).imag();
}

Vec rot(const Vec& a, T ang) {
    return a * Vec(std::cos(ang), std::sin(ang));
}

Vec perp(const Vec& a) {
    return Vec(-a.imag(), a.real());
}

Vec projection(const Line& l, const Vec& p) {
    return l.p1 + dot(p - l.p1, l.dir()) * l.dir() / std::norm(l.dir());
}

Vec reflection(const Line& l, const Vec& p) {
    return T(2) * projection(l, p) - p;
}

// 0: collinear
// 1: counter-clockwise
// -1: clockwise
int ccw(const Vec& a, const Vec& b, const Vec& c) {
    if (eq(cross(b - a, c - a), 0)) return 0;
    if (lt(cross(b - a, c - a), 0)) return -1;
    return 1;
}

void sort_by_arg(std::vector<Vec>& pts) {
    std::sort(pts.begin(), pts.end(), [&](auto& p, auto& q) {
        if ((p.imag() < 0) != (q.imag() < 0)) return (p.imag() < 0);
        if (cross(p, q) == 0) {
            if (p == Vec(0, 0)) return !(q.imag() < 0 || (q.imag() == 0 && q.real() > 0));
            if (q == Vec(0, 0)) return  (p.imag() < 0 || (p.imag() == 0 && p.real() > 0));
            return (p.real() > q.real());
        }
        return (cross(p, q) > 0);
    });
}

std::vector<Vec> intersection(const Circle& c1, const Circle& c2) {
    T d = std::abs(c1.c - c2.c);
    if (lt(c1.r + c2.r, d)) return {};  // outside
    Vec e1 = (c2.c - c1.c) / std::abs(c2.c - c1.c);
    Vec e2 = perp(e1);
    if (lt(d, std::abs(c2.r - c1.r))) return {};  // contain
    if (eq(d, std::abs(c2.r - c1.r))) return {c1.c + c1.r*e1};  // tangent
    T x = (c1.r*c1.r - c2.r*c2.r + d*d) / (2*d);
    T y = std::sqrt(c1.r*c1.r - x*x);
    return {c1.c + x*e1 + y*e2, c1.c + x*e1 - y*e2};
}

int intersect(const Circle& c1, const Circle& c2) {
    T d = std::abs(c1.c - c2.c);
    if (lt(d, std::abs(c2.r - c1.r))) return 0;
    if (eq(d, std::abs(c2.r - c1.r))) return 1;
    if (eq(c1.r + c2.r, d)) return 3;
    if (lt(c1.r + c2.r, d)) return 4;
    return 2;
}

struct Vec3 {
    T x, y, z;
    Vec3() = default;
    constexpr Vec3(T x, T y, T z) : x(x), y(y), z(z) {}
    constexpr Vec3& operator+=(const Vec3& r) { x += r.x; y += r.y; z += r.z; return *this; }
    constexpr Vec3& operator-=(const Vec3& r) { x -= r.x; y -= r.y; z -= r.z; return *this; }
    constexpr Vec3& operator*=(T r) { x *= r; y *= r; z *= r; return *this; }
    constexpr Vec3& operator/=(T r) { x /= r; y /= r; z /= r; return *this; }
    constexpr Vec3 operator-() const { return Vec3(-x, -y, -z); }
    constexpr Vec3 operator+(const Vec3& r) const { return Vec3(*this) += r; }
    constexpr Vec3 operator-(const Vec3& r) const { return Vec3(*this) -= r; }
    constexpr Vec3 operator*(T r) const { return Vec3(*this) *= r; }
    constexpr Vec3 operator/(T r) const { return Vec3(*this) /= r; }
    friend constexpr Vec3 operator*(T r, const Vec3& v) { return v * r; }
};

std::istream& operator>>(std::istream& is, Vec3& p) {
    T x, y, z;
    is >> x >> y >> z;
    p = {x, y, z};
    return is;
}

std::ostream& operator<<(std::ostream& os, const Vec3& p) {
    os << "(" << p.x << ", " << p.y << ", " << p.z << ")";
    return os;
}

T dot(const Vec3& a, const Vec3& b) {
    return a.x*b.x + a.y*b.y + a.z*b.z;
}

Vec3 cross(const Vec3& a, const Vec3& b) {
    return Vec3(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
}

namespace std {
T norm(const Vec3& a) { return dot(a, a); }
T abs(const Vec3& a) { return std::sqrt(std::norm(a)); }
}


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

    while (true) {
        int N;
        cin >> N;
        if (N == 0) break;
        vector<pair<Vec3, T>> sp;
        vector<T> events;
        rep(i,0,N) {
            Vec3 c;
            T r;
            cin >> c >> r;
            sp.push_back({c, r});
            events.push_back(c.z-r);
            events.push_back(c.z+r);
        }
        rep(i,0,N) rep(j,i+1,N) {
            auto [ci, ri] = sp[i];
            auto [cj, rj] = sp[j];
            Vec3 d = cj - ci;
            Circle cli(Vec(0, 0), ri);
            Circle clj(Vec(sqrt(d.x*d.x+d.y*d.y), d.z), rj);
            auto ints = intersection(cli, clj);
            if (ints.size() < 2) continue;
            T z0 = ints[0].imag() + ci.z;
            T z1 = ints[1].imag() + ci.z;
            events.push_back(z0);
            events.push_back(z1);
        }
        sort(all(events));
        string ans = "";
        int prv = 0;
        for (T z : events) {
            z += 10*eps;
            vector<bool> exist(N);
            UnionFind uf(N);
            vector<Circle> sections(N);
            rep(i,0,N) {
                auto [ci, ri] = sp[i];
                if (leq(ci.z-ri, z) && leq(z, ci.z+ri)) {
                    exist[i] = true;
                } else {
                    continue;
                }
                T dz = ci.z - z;
                sections[i] = Circle(Vec(ci.x, ci.y), sqrt(ri*ri-dz*dz));
            }
            rep(i,0,N) rep(j,i+1,N) {
                if (exist[i] && exist[j] && intersect(sections[i], sections[j]) != 4) {
                    uf.unite(i, j);
                }
            }
            set<int> st;
            rep(i,0,N) if (exist[i]) st.insert(uf.find(i));
            int cur = st.size();
            if (prv < cur) ans += '1';
            else if (prv > cur) ans += '0';
            prv = cur;
        }
        cout << ans.size() << endl;
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3492
final_rank: 11

code_snippet: #line 1 "1255.cpp"
/*	author:  Kite_kuma
	created: 2022.06.16 15:36:45 */

#line 2 "SPJ-Library/geometry/geometry.hpp"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <vector>

using R = long double;
using point = std::complex<R>;
using arrow = point;
const R EPS(1e-10), PI(acosl(-1));

inline bool eq(const R &a, const R &b) { return fabsl(b - a) < EPS; }
inline bool same_point(const point &a, const point &b) { return abs(b - a) < EPS; }
/*
	sign of x
	-1: x < 0
	 0: x == 0
	 1: x > 0
*/
inline int sgn(const R &x) { return fabsl(x) < EPS ? 0 : (x < 0 ? -1 : 1); }
/*
	sign of (a-b)
	-1: a < b
	 0: a == b
	 1: a > b
*/
inline int compare(const R &a, const R &b) { return eq(a, b) ? 0 : a < b ? -1 : 1; }

std::istream &operator>>(std::istream &is, point &p) {
	R a, b;
	is >> a >> b;
	p = point(a, b);
	return is;
}
std::ostream &operator<<(std::ostream &os, point &p) { return os << '(' << p.real() << ", " << p.imag() << ')'; }

// rotate point 'p' for counter clockwise direction
point rotate(const point &p, const R &theta) {
	return point(cosl(theta) * p.real() - sinl(theta) * p.imag(), sinl(theta) * p.real() + cosl(theta) * p.imag());
}

R radian_to_degree(const R &r) { return (r * 180.0 / PI); }
R degree_to_radian(const R &d) { return (d * PI / 180.0); }

// get angle a-b-c (<pi)
R get_angle(const point &a, const point &b, const point &c) {
	const point v(a - b), w(c - b);
	R theta = fabsl(atan2l(w.imag(), w.real()) - atan2l(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 segment;
struct line {
	point a, b;
	line() = default;
	line(const point &a, const point &b) : a(a), b(b) {}
	// Ax + By + C = 0
	line(const R &A, const R &B, const R &C) {
		if(eq(A, 0)) {
			assert(!eq(B, 0));
			a = point(0, -C / B), b = point(1, -(A + C) / B);
		} else {
			a = point(-C / A, 0), b = point(-(B + C) / A, 1);
		}
	}
	explicit line(const segment &seg);
	friend std::ostream &operator<<(std::ostream &os, line &ln) { return os << '(' << ln.a << " -- " << ln.b << ')'; }
	friend std::istream &operator>>(std::istream &is, line &a) { return is >> a.a >> a.b; }
};
struct segment {
	point a, b;
	segment() = default;
	segment(const point &a, const point &b) : a(a), b(b) {}
	explicit segment(const line &ln) : a(ln.a), b(ln.b) {}
	friend std::ostream &operator<<(std::ostream &os, segment &seg) { return os << '[' << seg.a << " -- " << seg.b << ']'; }
	friend std::istream &operator>>(std::istream &is, segment &a) { return is >> a.a >> a.b; }
};
line::line(const segment &seg) : a(seg.a), b(seg.b) {}

struct circle {
	point center;
	R radius;
	circle() = default;
	circle(const point &center, const R &radius) : center(center), radius(radius) {}
};

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

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

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

bool parallel(const arrow &a, const arrow &b) { return eq(cross(a, b), R(0)); }
bool parallel(const line &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const line &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const segment &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); }
bool parallel(const segment &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); }

bool orthogonal(const arrow &a, const arrow &b) { return eq(dot(a, b), R(0)); }
bool orthogonal(const line &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const line &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const segment &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); }
bool orthogonal(const segment &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); }

point projection(const line &l, const point &p) { return l.a + (l.a - l.b) * dot(p - l.a, l.a - l.b) / norm(l.a - l.b); }
point projection(const segment &s, const point &p) { return projection(line(s), p); }

point reflection(const line &l, const point &p) { return projection(l, p) * R(2) - p; }
point reflection(const segment &s, const point &p) { return projection(line(s), p); }

R distance(const point &p, const point &q);
R distance(const line &l, const point &p);
int number_of_common_tangents(const circle &c1, const circle &c2) {
	const R r1 = std::min(c1.radius, c2.radius), r2 = std::max(c1.radius, c2.radius), d = distance(c1.center, c2.center);
	int com = compare(r1 + r2, d);
	return com == 1 ? compare(d + r1, r2) + 1 : 3 - com;
}

// number of common points (-1: infinite)
int intersect(const line &l, const point &p) { return int(abs(ccw(l.a, l.b, p)) != 1); }
int intersect(const point &p, const line &l) { return intersect(l, p); }
int intersect(const line &l, const line &m) {
	if(intersect(l, m.a) && intersect(l, m.b)) return -1;
	return int(!parallel(l, m));
}
int intersect(const segment &s, const point &p) { return int(ccw(s.a, s.b, p) == CCW::ON_SEGMENT); }
int intersect(const point &p, const segment &s) { return intersect(s, p); }
int intersect(const line &l, const segment &s) {
	if(intersect(l, s.a) && intersect(l, s.b)) return -1;
	return ccw(l.a, l.b, s.a) * ccw(l.a, l.b, s.b) != 1;
}
int intersect(const segment &s, const line &l) { return intersect(l, s); }
int intersect(const circle &c, const line &l) {
	R d = c.radius - distance(l, c.center);
	return fabsl(d) < EPS ? 1 : d > 0. ? 2 : 0;
}
int intersect(const line &l, const circle &c) { return intersect(c, l); }
int intersect(const circle &c, const point &p) { return int(eq(c.radius, distance(c.center, p))); }
int intersect(const point &p, const circle &c) { return intersect(c, p); }
int intersect(const segment &s, const segment &t) {
	if(same_point(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 &s) {
	const point h = projection(s, c.center);
	const int c0 = compare(distance(h, c.center), c.radius);
	if(c0 == 1) return 0;
	if(c0 == 0) return intersect(s, h);
	const int c1 = compare(distance(c.center, s.a), c.radius), c2 = compare(distance(c.center, s.b), c.radius);
	if(std::min(c1, c2) == -1) return int(std::max(c1, c2) >= 0);
	return intersect(s, h) ? 2 : 0;
}
int intersect(const segment &s, const circle &c) { return intersect(c, s); }
int intersect(const circle &c1, const circle &c2) { return 2 - abs(2 - number_of_common_tangents(c1, c2)); }

// distance of two shaps
R distance(const point &a, const point &b) { return fabs(a - b); }
R distance(const line &l, const point &p) { return distance(p, projection(l, p)); }
R distance(const point &p, const line &l) { return distance(l, p); }
R distance(const line &l, const line &m) { return parallel(l, m) ? distance(l, m.a) : 0; }
R distance(const segment &s, const point &p) {
	const point r = projection(s, p);
	return intersect(s, r) ? distance(r, p) : std::min(distance(s.a, p), distance(s.b, p));
}
R distance(const point &p, const segment &s) { return distance(s, p); }
R distance(const segment &a, const segment &b) {
	if(intersect(a, b)) return R(0);
	return std::min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}
R distance(const line &l, const segment &s) {
	if(intersect(l, s)) return 0;
	return std::min(distance(l, s.a), distance(l, s.b));
}
R distance(const segment &s, const line &l) { return distance(l, s); }
R distance(const circle &c, const point &p) { return fabsl(distance(c.center, p) - c.radius); }
R distance(const point &p, const circle &c) { return distance(c, p); }
R distance(const circle &c, const line &l) { return std::max(R(0), distance(l, c.center) - c.radius); }
R distance(const line &l, const circle &c) { return distance(c, l); }
R distance(const circle &c1, const circle &c2) {
	const R d = distance(c1.center, c2.center);
	if(d > c1.radius + c2.radius) return d - c1.radius - c2.radius;
	if(d < fabsl(c1.radius - c2.radius)) return fabsl(c1.radius - c2.radius) - d;
	return R(0);
}
R distance(const circle &c, const segment &s) {
	const point p = projection(s, c.center);
	const R dist_min = intersect(s, p) ? distance(c.center, p) : std::min(distance(c.center, s.a), distance(c.center, s.b));
	if(dist_min > c.radius) return dist_min - c.radius;
	const R dist_max = std::max(distance(c.center, s.a), distance(c.center, s.b));
	return dist_max < c.radius ? c.radius - dist_max : R(0);
}
R distance(const segment &s, const circle &c) { return distance(c, s); }

point crosspoint(const line &l, const line &m) {
	R A = cross(l.b - l.a, m.b - m.a);
	R B = cross(l.b - l.a, l.b - m.a);
	if(eq(A, 0.)) return m.a;
	return m.a + (m.b - m.a) * B / A;
}
point crosspoint(const segment &s, const segment &t) { return crosspoint(line(s), line(t)); }
point crosspoint(const segment &s, const line &l) { return crosspoint(line(s), l); }
point crosspoint(const line &l, const segment &s) { return crosspoint(l, line(s)); }
points crosspoints(const circle &c, const line &l) {
	const point pr = projection(l, c.center);
	const R square = c.radius * c.radius - norm(pr - c.center);
	switch(sgn(square)) {
		case 0:
			return points{pr};
		case -1:
			return points(0);
	}
	const arrow v = (l.b - l.a) / abs(l.b - l.a) * sqrtl(square);
	return points{pr - v, pr + v};
}
points crosspoints(const line &l, const circle &c) { return crosspoints(c, l); }
points crosspoints(const circle &c, const segment &s) {
	points ret;
	for(const auto &pt : crosspoints(c, line(s)))
		if(intersect(s, pt)) ret.push_back(pt);
	return ret;
}
points crosspoints(const segment &s, const circle &c) { return crosspoints(c, s); }
points crosspoints(const circle &c1, const circle &c2) {
	R d = abs(c1.center - c2.center);
	if(compare(d, c1.radius + c2.radius) == 1) return points(0);
	if(compare(d, fabsl(c1.radius - c2.radius)) == -1) return points(0);
	bool one_crosspoint = false;
	if(eq(d, c1.radius + c2.radius) || eq(d, fabsl(c1.radius - c2.radius))) one_crosspoint = true;
	const R alpha = acosl((c1.radius * c1.radius + d * d - c2.radius * c2.radius) / (2 * c1.radius * d));  // cosine theorem
	const R beta = std::arg(c2.center - c1.center);
	if(one_crosspoint) return points{c1.center + std::polar(c1.radius, beta + alpha)};
	return points{c1.center + std::polar(c1.radius, beta + alpha), c1.center + std::polar(c1.radius, beta - alpha)};
}

points tangent_points(const circle &c, const point &p) {
	const R square = norm(c.center - p) - c.radius * c.radius;
	switch(sgn(square)) {
		case 0:
			return points{p};
		case -1:
			return points{};
	}
	return crosspoints(c, circle(p, sqrtl(square)));
}

// common tangents of two circles
lines tangents(circle c1, circle c2) {
	lines ret;
	if(c1.radius < c2.radius) std::swap(c1, c2);
	const R g = distance(c1.center, c2.center);
	if(!sgn(g)) return ret;
	const arrow u = (c2.center - c1.center) / g;
	const arrow v = rotate(u, PI * 0.5);
	for(const int &s : {-1, 1}) {
		const R h = (c1.radius + s * c2.radius) / g;
		if(eq(1 - h * h, 0)) {
			ret.emplace_back(c1.center + u * c1.radius, c1.center + (u + v) * c1.radius);
		} else if(1 - h * h > 0) {
			const point uu = u * h, vv = v * sqrtl(1 - h * h);
			ret.emplace_back(c1.center + (uu + vv) * c1.radius, c2.center - (uu + vv) * c2.radius * R(s));
			ret.emplace_back(c1.center + (uu - vv) * c1.radius, c2.center - (uu - vv) * c2.radius * R(s));
		}
	}
	return ret;
}
#line 2 "SPJ-Library/geometry/contain.hpp"

enum CONTAIN { OUT = 0, ON = 1, IN = 2 };
int contains(const polygon &poly, const point &p) {
	bool in = false;
	for(int i = 0; i < poly.size(); i++) {
		point a = poly[i], b = poly[(i + 1) % poly.size()];
		if(ccw(a, b, p) == 0) return CONTAIN::ON;
		if(a.imag() > b.imag()) swap(a, b);
		if(a.imag() <= p.imag() && p.imag() < b.imag() && cross(a - p, b - p) < 0) in = !in;
	}
	return in ? CONTAIN::IN : CONTAIN::OUT;
}
int contains(const circle &c, const point &p) { return compare(c.radius, distance(c.center, p)) + 1; }
#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#line 5 "SPJ-Library/template/basic_func.hpp"
#include <iostream>
#line 7 "SPJ-Library/template/basic_func.hpp"

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 flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\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(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

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

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

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

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, const 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 (int)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 (int)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(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

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

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>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

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
#line 7 "SPJ-Library/template/io.hpp"

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

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

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(typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); it++) {
		if(it != v.begin()) std::cerr << ' ';
		os << *it;
	}
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(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))

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>;
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>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 7 "1255.cpp"

string solve(int n) {
	const int dim = 3;
	vector<array<R, dim>> centers;
	vector<R> radius;
	rep(n) {
		array<R, dim> cent;
		rep(i, dim) cin >> cent[i];
		centers.push_back(cent);
		R r;
		cin >> r;
		radius.push_back(r);
	}

	vector<tuple<R, int, int>> events;

	vector<int> notuse(n);
	rep(i, n) {
		const R xi = centers[i][0];
		const R yi = centers[i][1];
		const R zi = centers[i][2];
		events.emplace_back(zi - radius[i], i, -1);
		events.emplace_back(zi + radius[i], i, -1);
		rep(j, i + 1, n) {
			const R xj = centers[j][0];
			const R yj = centers[j][1];
			const R zj = centers[j][2];
			const R distxy = distance(point(xi, yi), point(xj, yj));
			circle ci(point(0, zi), radius[i]), cj(point(distxy, zj), radius[j]);

			const int cross = number_of_common_tangents(ci, cj);
			assert(cross != 1 && cross != 3);
			if(cross == 2) {
				const points cpts = crosspoints(ci, cj);
				R zmin = cpts.front().imag();
				R zmax = cpts.back().imag();
				if(zmin > zmax) swap(zmin, zmax);
				debug(i, j, zmin, zmax);
				auto update_point = [&](point p) {
					if(contains(ci, p) == CONTAIN::OUT) return;
					if(contains(cj, p) == CONTAIN::OUT) return;
					R znew = p.imag();
					chmax(zmax, znew);
					chmin(zmin, znew);
					return;
				};
				update_point(ci.center + arrow(0, radius[i]));
				update_point(ci.center - arrow(0, radius[i]));
				update_point(cj.center + arrow(0, radius[j]));
				update_point(cj.center - arrow(0, radius[j]));
				events.emplace_back(zmin - EPS, i, j);
				events.emplace_back(zmax + EPS, i, j);
			} else if(cross == 0) {
				int erase = i;
				if(radius[j] < radius[i]) erase = j;
				notuse[erase] = 1;
			}
		}
	}

	sort(all(events));

	vector<int> exists(n);
	vector<vector<int>> edge(n, vi(n));

	debug(events);

	vector<int> visited(n);
	auto dfs = [&](auto dfs, int now) -> void {
		debug(now, visited);
		visited[now] = 1;
		rep(nxt, n) {
			if(visited[nxt] || !exists[nxt] || !edge[now][nxt]) continue;
			dfs(dfs, nxt);
		}
		return;
	};

	auto components = [&]() -> int {
		visited.assign(n, 0);
		int ret = 0;
		debug(exists);
		rep(i, n) if(exists[i] && !visited[i]) {
			dfs(dfs, i);
			ret++;
		}
		return ret;
	};

	string ans;
	int c = 0;
	for(auto [z, i, j] : events) {
		if(notuse[i]) continue;
		if(j == -1) {
			exists[i] ^= 1;
		} else {
			if(notuse[j]) continue;
			edge[i][j] ^= 1;
			edge[j][i] ^= 1;
		}
		int c_new = components();
		if(c < c_new)
			ans += '1';
		else if(c > c_new)
			ans += '0';
		c = c_new;
	}
	return ans;
}
int main() {
	int n;
	while(cin >> n && n) {
		string ans = solve(n);
		print(ans.size());
		cout << ans << '\n';
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3960
final_rank: 10

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

using namespace std;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

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

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

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

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

// ------------------ ACL --------------------

// #include <atcoder/modint>
// constexpr int MOD = 998244353;
// constexpr int MOD = 1000000007;
// using mint = atcoder::static_modint<MOD>;
// ostream &operator<<(ostream &os, const mint &v) {
//   return os << v.val();
// }

// ------------ End of template --------------

// Geometry Library
// written by okuraofvegetable

#define pb push_back
#define DOUBLE_INF 1e50
#define Points vector<Point>

#define EQ(a, b) (abs((a) - (b)) < eps)
#define GT(a, b) ((a) > (b))
#define GE(a, b) (GT(a, b) || EQ(a, b))
#define LT(a, b) ((a) < (b))
#define LE(a, b) (LT(a, b) || EQ(a, b))

#define double long double

inline double add(double a, double b) {
  if (abs(a + b) < eps * (abs(a) + abs(b))) return 0;
  return a + b;
}

// --------------------- Point -----------------------

#define Vector Point
struct Point {
  double x, y;
  Point() {}
  Point(double x, double y) : x(x), y(y) {}
  Point operator+(Point p) { return Point(add(x, p.x), add(y, p.y)); }
  Point operator-(Point p) { return Point(add(x, -p.x), add(y, -p.y)); }
  Point operator*(double d) { return Point(x * d, y * d); }
  Point operator/(double d) { return Point(x / d, y / d); }
  double dot(Point p) { return add(x * p.x, y * p.y); }
  double det(Point p) { return add(x * p.y, -y * p.x); }
  double norm() { return sqrt(x * x + y * y); }
  double norm2() { return x * x + y * y; }
  double dist(Point p) { return ((*this) - p).norm(); }
  double dist2(Point p) { return sq(x - p.x) + sq(y - p.y); }
  double arg() { return atan2(y, x); }             // [-PI,PI]
  double arg(Vector v) { return v.arg() - arg(); } // henkaku
  double angle(Vector v) {                         // [0,PI]
    return acos(cos(arg(v)));
  }
  Vector normalize() { return (*this) * (1.0 / norm()); }
  Point vert() { return Point(y, -x); }

  // Signed area of triange (0,0) (x,y) (p.x,p.y)
  double area(Point p) { return (x * p.y - p.x * y) / 2.0; }
  friend istream &operator>>(istream &is, Point &p) { return is >> p.x >> p.y; }
  friend ostream &operator<<(ostream &os, const Point &p) {
    return os << '(' << p.x << ',' << p.y << ')';
  }
};

Point divide_rate(Point a, Point b, double A, double B) {
  assert(!EQ(A + B, 0.0));
  return (a * B + b * A) * (1.0 / (A + B));
}

Vector polar(double len, double arg) {
  return Vector(cos(arg) * len, sin(arg) * len);
}

// Direction a -> b -> c
// verified AOJ CGL_1_C
enum { COUNTER_CLOCKWISE, CLOCKWISE, ONLINE_BACK, ONLINE_FRONT, ON_SEGMENT };
int ccw(Point a, Point b, Point c) {
  Vector p = b - a;
  Vector q = c - a;
  if (p.det(q) > 0.0) return COUNTER_CLOCKWISE; // counter clockwise
  if (p.det(q) < 0.0) return CLOCKWISE;         // clockwise
  if (p.dot(q) < 0.0) return ONLINE_BACK;       // c--a--b online_back
  if (p.norm() < q.norm()) return ONLINE_FRONT; // a--b--c online_front
  return ON_SEGMENT;                            // a--c--b on_segment
}

// --------------------- Line ------------------------
struct Line {
  Point a, b;
  Line() {}
  Line(Point a, Point b) : a(a), b(b) {}
  bool on(Point q) { return EQ((a - q).det(b - q), 0.0); }
  // following 2 functions verified AOJ CGL_2_A
  bool is_parallel(Line l) { return EQ((a - b).det(l.a - l.b), 0.0); }
  bool is_orthogonal(Line l) { return EQ((a - b).dot(l.a - l.b), 0.0); }
  Point intersection(Line l) {
    assert(!is_parallel(l));
    return a + (b - a) * ((l.b - l.a).det(l.a - a) / (l.b - l.a).det(b - a));
  }
  // Projection of p to this line
  // verified AOJ CGL_1_A
  Point projection(Point p) {
    return (b - a) * ((b - a).dot(p - a) / (b - a).norm2()) + a;
  }
  double distance(Point p) {
    Point q = projection(p);
    return p.dist(q);
  }
  // Reflection point of p onto this line
  // verified AOJ CGL_1_B
  Point refl(Point p) {
    Point proj = projection(p);
    return p + ((proj - p) * 2.0);
  }
  bool left(Point p) {
    if ((p - a).det(b - a) > 0.0)
      return true;
    else
      return false;
  }
  friend istream &operator>>(istream &is, Line &l) { return is >> l.a >> l.b; }
  friend ostream &operator<<(ostream &os, const Line &l) {
    return os << l.a << " -> " << l.b;
  }
};

// ------------------- Segment  ----------------------
struct Segment {
  Point a, b;
  Segment() {}
  Segment(Point a, Point b) : a(a), b(b) {}
  Line line() { return Line(a, b); }
  bool on(Point q) {
    return (EQ((a - q).det(b - q), 0.0) && LE((a - q).dot(b - q), 0.0));
  }
  // verified AOJ CGL_2_B
  bool is_intersect(Segment s) {
    if (line().is_parallel(s.line())) {
      if (on(s.a) || on(s.b)) return true;
      if (s.on(a) || s.on(b)) return true;
      return false;
    }
    Point p = line().intersection(s.line());
    if (on(p) && s.on(p))
      return true;
    else
      return false;
  }
  bool is_intersect(Line l) {
    if (line().is_parallel(l)) {
      if (l.on(a) || l.on(b))
        return true;
      else
        return false;
    }
    Point p = line().intersection(l);
    if (on(p))
      return true;
    else
      return false;
  }
  // following 2 distance functions are verified at AOJ CGL_2_D
  double distance(Point p) {
    double res = DOUBLE_INF;
    Point q = line().projection(p);
    if (on(q)) res = min(res, p.dist(q));
    res = min(res, min(p.dist(a), p.dist(b)));
    return res;
  }
  double distance(Segment s) {
    if (is_intersect(s)) return 0.0;
    double res = DOUBLE_INF;
    res = min(res, s.distance(a));
    res = min(res, s.distance(b));
    res = min(res, this->distance(s.a));
    res = min(res, this->distance(s.b));
    return res;
  }
  friend istream &operator>>(istream &is, Segment &s) {
    return is >> s.a >> s.b;
  }
  friend ostream &operator<<(ostream &os, const Segment &s) {
    return os << s.a << " -> " << s.b;
  }
};

// ------------------- Polygon -----------------------
// Note: A polygon generally don't need to be convex.

typedef vector<Point> Polygon;
// verified AOJ CGL_3_A
double area(Polygon &pol) {
  Points vec;
  double res = 0.0;
  int M = pol.size();
  for (int i = 0; i < M; i++) {
    res += (pol[i] - pol[0]).area(pol[(i + 1) % M] - pol[0]);
  }
  return res;
}

bool is_convex(Polygon &pol) {
  int n = pol.size();
  for (int i = 0; i < n - 1; i++) {
    if (ccw(pol[i], pol[i + 1], pol[(i + 2) % n]) == CLOCKWISE) {
      return false;
    }
  }
  return true;
}

// vecrified AOJ CGL_3_C
enum { OUT, ON, IN };
int contained(Polygon &pol, Point p) {
  int n = pol.size();
  Point outer(1e9, p.y);
  int cnt = 0;
  for (int i = 0; i < n; i++) {
    Segment e = Segment(pol[i], pol[(i + 1) % n]);
    if (e.on(p)) return ON;
    Vector a = pol[i] - p;
    Vector b = pol[(i + 1) % n] - p;
    if (a.y > b.y) swap(a, b);
    if (LE(a.y, 0.0) && GT(b.y, 0.0)) {
      if (LT(a.det(b), 0.0)) cnt++;
    }
  }
  if ((cnt & 1) == 1)
    return IN;
  else
    return OUT;
}

// A compare function for convex_hull
// sort points by (x-y) lexicographical order.
// you can change (y-x) order with no change in convex_hull
bool comp(const Point &p, const Point &q) {
  if (!EQ(p.x, q.x))
    return p.x < q.x;
  else
    return p.y < q.y;
}

// Convex hull
// if you want not to contain points on boundary,
// change while(....<=0.0)
// verified AOJ CGL_4_A
Polygon convex_hull(vector<Point> ps) {
  sort(all(ps), comp);
  int k = 0;
  int n = ps.size();
  Polygon qs(2 * n);
  for (int i = 0; i < n; i++) {
    while (k > 1 && LT((qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]), 0.0))
      k--;
    qs[k++] = ps[i];
  }
  for (int i = n - 2, t = k; i >= 0; i--) {
    while (k > t && LT((qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]), 0.0))
      k--;
    qs[k++] = ps[i];
  }
  qs.resize(k - 1);
  return qs;
}

// Caliper method
// verified AOJ CGL_4_B
double convex_diameter(Polygon &cv) {
  int i = 0, j = 0;
  int n = cv.size();
  for (int k = 0; k < n; k++) {
    if (!comp(cv[i], cv[k])) i = k;
    if (comp(cv[j], cv[k])) j = k;
  }
  int si = i, sj = j;
  double res = 0.0;
  while (i != sj || j != si) {
    res = max(res, cv[i].dist(cv[j]));
    if ((cv[(i + 1) % n] - cv[i]).det(cv[(j + 1) % n] - cv[j]) < 0.0)
      i = (i + 1) % n;
    else
      j = (j + 1) % n;
  }
  return res;
}

// Cut conovex polygon by a line and return left polygon
// verified AOJ CGL_4_C
Polygon convex_cut(Polygon &cv, Line l) {
  int n = cv.size();
  Polygon left;
  for (int i = 0; i < n; i++) {
    Segment e = Segment(cv[i], cv[(i + 1) % n]);
    if (ccw(l.a, l.b, cv[i]) != CLOCKWISE) left.pb(cv[i]);
    if (e.is_intersect(l)) {
      if (!e.line().is_parallel(l)) { left.pb(e.line().intersection(l)); }
    }
  }
  return left;
}

// Distance between closest pair
// verified CGL_5_A
bool comp_y(const Point &p, const Point &q) {
  return p.y < q.y;
}
double closest_pair(vector<Point>::iterator a, int n) {
  if (n <= 1) return DOUBLE_INF;
  int m = n / 2;
  double x = (a + m)->x;
  double d = min(closest_pair(a, m), closest_pair(a + m, n - m));
  inplace_merge(a, a + m, a + n, comp_y);
  vector<Point> b;
  for (int i = 0; i < n; i++) {
    double ax = (a + i)->x;
    double ay = (a + i)->y;
    if (abs(ax - x) >= d) continue;
    for (int j = 0; j < b.size(); j++) {
      double dx = ax - b[b.size() - 1 - j].x;
      double dy = ay - b[b.size() - 1 - j].y;
      if (dy >= d) break;
      d = min(d, sqrt(dx * dx + dy * dy));
    }
    b.pb(*(a + i));
  }
  return d;
}
double closest_pair(vector<Point> a) {
  sort(all(a), comp);
  return closest_pair(a.begin(), (int)a.size());
}

// -------------------- Circle -----------------------

// Relationship between two circles
// Each value as integer corresponds to the number of common tangent lines.
// (e.g. When two circles are circumscribed with each other, there are 3 common
// tangent lines.)
enum {
  INCLUDE,
  INSCRIBED, // "Naisetsu" in Japanese
  INTERSECT,
  CIRCUMSCRIBED, // "Gaisetsu" in Japanese
  NOT_CROSS,
};

struct Circle {
  Point center;
  double r;
  Circle() {}
  Circle(Point c, double r) : center(c), r(r) {}
  bool in(Point p) { return p.dist(center) < r; }
  // verified AOJ CGL_7_A
  int is_intersect(Circle c) {
    double cd = center.dist(c.center);
    if (EQ(cd, r + c.r)) return CIRCUMSCRIBED;
    if (EQ(cd, abs(r - c.r))) return INSCRIBED;
    if (cd > r + c.r)
      return NOT_CROSS;
    else if (cd > abs(r - c.r))
      return INTERSECT;
    else
      return INCLUDE;
  }
  // verified AOJ CGL_7_D
  Points intersection(Line l) {
    Points res;
    double d = l.distance(center);
    if (EQ(d, r)) {
      res.pb(l.projection(center));
    } else if (d < r) {
      double k = sqrt(r * r - d * d);
      Vector v = (l.a - l.b).normalize() * k;
      res.pb(l.projection(center) + v);
      res.pb(l.projection(center) - v);
    }
    return res;
  }
  Points intersection(Segment s) {
    Points tmp = intersection(s.line());
    Points res;
    for (int i = 0; i < tmp.size(); i++) {
      if (s.on(tmp[i])) res.pb(tmp[i]);
    }
    return res;
  }
  Points intersection(Circle c) {
    Points res;
    double d = (c.center - center).norm();
    double a = acos((r * r + d * d - c.r * c.r) / (2.0 * r * d));
    double t = (c.center - center).arg();
    res.pb(center + polar(r, t + a));
    res.pb(center + polar(r, t - a));
    return res;
  }
  Points tangent(Point p) {
    Points res;
    double d = center.dist(p);
    double a = asin(r / d);
    double t = (center - p).arg();
    double len = sqrt(d * d - r * r);
    res.pb(p + polar(len, t + a));
    res.pb(p + polar(len, t - a));
    return res;
  }
  // verified CGL_7_G
  Points common_tangent(Circle c) {
    Points res;
    int state = is_intersect(c);
    if (EQ(r, c.r)) { // radius of the two circles are same
      Point p = divide_rate(center, c.center, r, c.r);
      Vector v = (c.center - center).vert().normalize() * r;
      if (state == INCLUDE)
        return res;
      else if (state == INSCRIBED) {
        cerr << "Same Circle" << endl;
        assert(false);
      } else if (state == INTERSECT) {
        res.pb(center + v);
        res.pb(center - v);
        return res;
      } else if (state == CIRCUMSCRIBED) {
        res.pb(center + v);
        res.pb(center - v);
        res.pb(p);
        return res;
      } else { // NOT_CROSS
        res = tangent(p);
        res.pb(center + v);
        res.pb(center - v);
        return res;
      }
    } else {
      Point p = divide_rate(center, c.center, r, c.r);
      Point q = divide_rate(center, c.center, r, -c.r);
      if (state == INCLUDE)
        return res;
      else if (state == INSCRIBED) {
        res.pb(q);
        return res;
      } else if (state == INTERSECT) {
        return tangent(q);
      } else if (state == CIRCUMSCRIBED) {
        res = tangent(q);
        res.pb(p);
        return res;
      } else { // NOT_CROSS
        res = tangent(p);
        Points add = tangent(q);
        for (int i = 0; i < add.size(); i++) res.pb(add[i]);
        return res;
      }
    }
  }
  // Area of intersection between this circle
  // and left side of given line l.
  // "left" is defined by considering line as directed vector(l.a -> l.b)
  // note: this function has not been verified yet.
  double left_area(Line l) {
    Points res = intersection(l);
    if (res.size() < 2) {
      if (l.left(center))
        return M_PI * r * r;
      else
        return 0.0;
    }
    Vector a = res[0] - center;
    Vector b = res[1] - center;
    double tri = abs(a.area(b));
    double fan = r * r * abs(a.arg(b)) / 2.0;
    if (l.left(center))
      return M_PI * r * r - (fan - tri);
    else
      return fan - tri;
  }
  // Returen signed area of intersection
  // between triangle(center-a-b) and this circle
  // verified AOJ CGL_7_H
  double area_intersection_triangle(Point a, Point b) {
    Segment s = Segment(a, b);
    double res = abs((a - center).area(b - center));
    if (EQ(res, 0.0)) return 0.0;
    if (in(a) && !in(b)) {
      Point p = intersection(s)[0];
      Point q = intersection(Segment(center, b))[0];
      res -= abs((p - b).area(q - b));
      res -= abs((p - center).area(q - center));
      res += abs(r * r * ((p - center).angle(b - center)) / 2.0);
    } else if (!in(a) && in(b)) {
      Point p = intersection(s)[0];
      Point q = intersection(Segment(center, a))[0];
      res -= abs((p - a).area(q - a));
      res -= abs((p - center).area(q - center));
      res += abs(r * r * ((p - center).angle(a - center)) / 2.0);
    } else if (!in(a) && !in(b)) {
      Points ps = intersection(s);
      if (ps.size() == 2) {
        Point p = ps[0];
        Point q = ps[1];
        Point m = divide_rate(p, q, 1.0, 1.0);
        res = abs(area_intersection_triangle(a, m)) +
              abs(area_intersection_triangle(m, b));
      } else {
        res = (r * r * (a - center).angle(b - center) / 2.0);
      }
    }
    if ((a - center).det(b - center) < 0.0) res = -res;
    return res;
  }
  // Area of intersection between given polygon and
  // this circle. polygon don't need to be convex
  double area_intersection_polygon(Polygon pol) {
    int n = pol.size();
    double res = 0.0;
    for (int i = 0; i < n; i++) {
      double tmp = area_intersection_triangle(pol[i], pol[(i + 1) % n]);
      res += tmp;
    }
    return abs(res);
  }
  friend istream &operator>>(istream &is, Circle &c) {
    return is >> c.center >> c.r;
  }
  friend ostream &operator<<(ostream &os, const Circle &c) {
    return os << c.center << " , rad: " << c.r;
  }
};

struct UnionFind {
  vector<int> par, rank, sz;
  UnionFind(int n) {
    par.assign(n, 0);
    rank.assign(n, 0);
    sz.assign(n, 1);
    for (int i = 0; i < n; i++) par[i] = i;
  }
  int find(const int x) { return (par[x] == x) ? x : (par[x] = find(par[x])); }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) {
      par[x] = y;
      sz[y] += sz[x];
    } else {
      par[y] = x;
      sz[x] += sz[y];
      if (rank[x] == rank[y]) rank[x]++;
    }
  }
  bool same(const int x, const int y) { return find(x) == find(y); }
  int size(const int x) { return sz[find(x)]; }
  vector<vector<int>> components() {
    int n = par.size();
    vector<vector<int>> cs;
    vector<int> idx(n, -1);
    for (int i = 0; i < n; i++) {
      if (find(i) != i) continue;
      idx[i] = cs.size();
      cs.emplace_back();
    }
    for (int i = 0; i < n; i++) {
      int id = idx[find(i)];
      cs[id].push_back(i);
    }
    return cs;
  }
};

#define endl "\n"
// #define int long long
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

bool solve() {
  int N;
  cin >> N;
  if (N == 0) return false;

  vector<double> X(N), Y(N), Z(N), R(N);
  for (int i = 0; i < N; i++) { cin >> X[i] >> Y[i] >> Z[i] >> R[i]; }

  auto cut_z = [&](int id, double z) {
    double zdiff = abs(Z[id] - z);
    if (zdiff > R[id]) return Circle(Point(0, 0), 0);
    double r = sqrtl(sq((double)R[id]) - sq(zdiff));
    assert(!isnan(r));
    return Circle(Point(X[id], Y[id]), r);
  };

  double fluc = 0.001;
  vector<double> zs;
  zs.push_back(0);
  zs.push_back(36000);
  {
    vector<Circle> cs;
    for (int i = 0; i < N; i++) { cs.emplace_back(Point(X[i], Z[i]), R[i]); }
    for (int i = 0; i < N; i++) {
      for (int d = -1; d <= 1; d++) {
        zs.push_back(Z[i] - R[i] + fluc * d);
        zs.push_back(Z[i] + R[i] + fluc * d);
      }
      for (int j = 0; j < N; j++) {
        if (i == j) continue;
        double dist = sq(X[i] - X[j]) + sq(Y[i] - Y[j]) + sq(Z[i] - Z[j]);
        if (dist > sq(R[i] + R[j])) continue;
        if (dist < sq(R[i] - R[j])) continue;
        double inter_z = Z[i] + (Z[j] - Z[i]) / sqrtl(dist) * (R[i] - eps);
        double ub = (double)std::max(Z[i] + R[i], Z[j] + R[j]) + eps;
        double lb = (double)std::min(Z[i] - R[i], Z[j] - R[j]) - eps;
        {
          double l = lb, r = inter_z;
          for (int _ = 0; _ < 30; _++) {
            double mid = (l + r) / 2.0;
            Circle a = cut_z(i, mid);
            Circle b = cut_z(j, mid);
            if (a.r == 0 || b.r == 0) {
              l = mid;
              continue;
            }
            if (a.is_intersect(b) == NOT_CROSS)
              l = mid;
            else
              r = mid;
          }
          for (int d = -1; d <= 1; d++) { zs.push_back(r + fluc * d); }
        }
        {
          double l = inter_z, r = ub;
          for (int _ = 0; _ < 30; _++) {
            double mid = (l + r) / 2.0;
            Circle a = cut_z(i, mid);
            Circle b = cut_z(j, mid);
            if (a.r == 0 || b.r == 0) {
              r = mid;
              continue;
            }
            if (a.is_intersect(b) == NOT_CROSS)
              r = mid;
            else
              l = mid;
          }
          for (int d = -1; d <= 1; d++) { zs.push_back(l + fluc * d); }
        }
      }
    }
  }
  sort(all(zs));

  // INCLUDE,
  // INSCRIBED, // "Naisetsu" in Japanese
  // INTERSECT,
  // CIRCUMSCRIBED, // "Gaisetsu" in Japanese
  // NOT_CROSS,

  auto calc = [&](double z) {
    vector<Circle> cs;
    for (int i = 0; i < N; i++) {
      double zdiff = abs(Z[i] - z);
      if (zdiff > R[i]) continue;
      double r = sqrtl(sq((double)R[i]) - sq(zdiff));
      assert(!isnan(r));
      cs.emplace_back(Point(X[i], Y[i]), r);
    }

    UnionFind uf(cs.size());
    for (int i = 0; i < cs.size(); i++) {
      for (int j = i + 1; j < cs.size(); j++) {
        int res = cs[i].is_intersect(cs[j]);
        if (res != NOT_CROSS) { uf.unite(i, j); }
      }
    }

    int num_cmp = 0;
    for (int i = 0; i < cs.size(); i++) {
      if (uf.find(i) == i) num_cmp++;
    }

    return num_cmp;
  };

  vector<int> ans;
  ans.push_back(0);
  for (auto z : zs) {
    ans.push_back(calc(z));
    dmp(z, ans.back());
  }
  ans.push_back(0);

  dmp(ans);
  ans.erase(unique(all(ans)), ans.end());
  dmp(ans);
  string str;
  for (int i = 1; i < ans.size(); i++) {
    assert(ans[i - 1] != ans[i]);
    if (ans[i - 1] < ans[i])
      str += "1";
    else
      str += "0";
  }

  cout << str.size() << endl;
  cout << str << endl;

  return true;
}

signed main() {
  fastio();
  if (!multitest) {
    while (solve()) {}
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3596
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
struct point{
  double x, y, z;
  point(){
  }
  point(double x, double y, double z): x(x), y(y), z(z){
  }
  point operator +(point P){
    return point(x + P.x, y + P.y, z + P.z);
  }
  point operator -(point P){
    return point(x - P.x, y - P.y, z - P.z);
  }
  point operator *(double k){
    return point(x * k, y * k, z * k);
  }
  point operator /(double k){
    return point(x / k, y / k, z / k);
  }
};
double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y + P.z * P.z);
}
double dist(point P, point Q){
  return abs(Q - P);
}
int main(){
  while (true){
    int N;
    cin >> N;
    if (N == 0){
      break;
    }
    vector<point> O(N);
    vector<double> R(N);
    for (int i = 0; i < N; i++){
      cin >> O[i].x >> O[i].y >> O[i].z >> R[i];
    }
    vector<point> A = O, B = O;
    for (int i = 0; i < N; i++){
      A[i].z -= R[i];
      B[i].z += R[i];
    }
    vector<double> upd;
    upd.push_back(0);
    upd.push_back(36000);
    for (int i = 0; i < N; i++){
      upd.push_back(O[i].z - R[i]);
      upd.push_back(O[i].z + R[i]);
      for (int j = i + 1; j < N; j++){
        double d = dist(O[i], O[j]);
        if (abs(R[i] - R[j]) < d && d < R[i] + R[j]){
          double m = (R[i] * R[i] + d * d - R[j] * R[j]) / (2 * d);
          double r = sqrt(R[i] * R[i] - m * m);
          point P = O[i] + (O[j] - O[i]) / d * m;
          point Q = O[j] - O[i];
          double a = sqrt(Q.x * Q.x + Q.y * Q.y) / d * r;
          upd.push_back(P.z - a);
          upd.push_back(P.z + a);
        }
      }
    }
    sort(upd.begin(), upd.end());
    int M = upd.size();
    vector<point> O2 = O;
    for (int i = 0; i < N; i++){
      O2[i].z = 0;
    }
    vector<vector<double>> d(N, vector<double>(N));
    for (int i = 0; i < N; i++){
      for (int j = 0; j < N; j++){
        d[i][j] = dist(O2[i], O2[j]);
      }
    }
    vector<int> cc;
    for (int i = 0; i < M - 1; i++){
      double z = (upd[i] + upd[i + 1]) / 2;
      vector<double> r(N, 0);
      for (int j = 0; j < N; j++){
        if (O[j].z - R[j] < z && z < O[j].z + R[j]){
          r[j] = sqrt(R[j] * R[j] - (O[j].z - z) * (O[j].z - z));
        }
      }
      vector<bool> used(N, false);
      int cnt = 0;
      for (int j = 0; j < N; j++){
        if (r[j] > 0 && !used[j]){
          used[j] = true;
          queue<int> Q;
          Q.push(j);
          while (!Q.empty()){
            int v = Q.front();
            Q.pop();
            for (int w = 0; w < N; w++){
              if (!used[w] && r[w] > 0 && d[v][w] < r[v] + r[w]){
                used[w] = true;
                Q.push(w);
              }
            }
          }
          cnt++;
        }
      }
      cc.push_back(cnt);
    }
    string ans;
    for (int i = 0; i < M - 2; i++){
      if (cc[i] > cc[i + 1]){
        ans += '0';
      }
      if (cc[i] < cc[i + 1]){
        ans += '1';
      }
    }
    cout << ans.size() << endl;
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3312
final_rank: 6

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 12345678;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-10;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 21;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}


typedef complex<ld> Point;
ld dot(Point a, Point b) { return real(conj(a) * b); }
ld cross(Point a, Point b) { return imag(conj(a) * b); }
namespace std {
	bool operator<(const Point& lhs, const Point& rhs) {
		return lhs.real() == rhs.real() ? lhs.imag() < rhs.imag() : lhs.real() < rhs.real();
	}
}
struct Line {
	Point a, b;
};
struct Circle {
	Point p; ld r;
};
int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps)return 1;//counter clockwise
	if (cross(b, c) < -eps)return -1;//clock wise
	if (dot(b, c) < 0)return 2;//c--a--b on line
	if (norm(b) < norm(c))return -2;//a--b--c on line
	return 0; //a--c--b on line
}
vector<Point> is_cc(Circle c1, Circle c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps)dfr = 0.0;
	if (dfr < 0.0)return res;
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0)res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

int n;
void solve() {
	vector<int> r(n);
	vector<int> x(n), y(n), z(n);
	rep(i, n) {
		cin >> x[i] >> y[i] >> z[i]>>r[i];
	}
	vector<ld> vs;
	rep(i, n) {
		vs.push_back(z[i] - r[i] + eps);
		vs.push_back(z[i] + r[i] + eps);
		Rep(j, i + 1, n) {
			ld dx = x[j] - x[i];
			ld dy = y[j] - y[i];
			ld dxy = sqrtl(dx * dx + dy * dy);
			Circle cl = { Point{(ld)0,(ld)z[i]},(ld)r[i] };
			Circle cr = { Point{(ld)dxy,(ld)z[j]},(ld)r[j] };
			vector<Point> vc = is_cc(cl, cr);
			for (auto p : vc) {
				vs.push_back(imag(p) + eps);
			}
		}
	}
	sort(all(vs));
	int cur = 0;
	string ans;
	vector<vector<ld>> dist(n, vector<ld>(n));
	rep(i, n)rep(j, n) {
		ld dx = x[j] - x[i];
		ld dy = y[j] - y[i];
		dist[i][j] = sqrtl(dx * dx + dy * dy);
	}
	for(auto val:vs){
		vector<vector<int>> G(n);
		vector<ld> rz(n);
		rep(i, n) {
			ld dz = abs(z[i] - val);
			if (dz <= r[i]) {
				rz[i] = sqrtl(r[i] * r[i] - dz * dz);
			}
			else {
				rz[i] = -1;
			}
		}
		rep(i, n)Rep(j, i + 1, n) {
			if (rz[i] >= 0 && rz[j] >= 0) {
				if (dist[i][j] <= rz[i] + rz[j]) {
					G[i].push_back(j);
					G[j].push_back(i);
				}
			}
		}
		vector<bool> used(n);
		int cnt = 0;
		rep(i, n) {
			if (rz[i] < 0)continue;
			if(used[i])continue;
			cnt++;
			queue<int> q; q.push(i);
			while (!q.empty()) {
				int v = q.front(); q.pop();
				for (int to : G[v])if (!used[to]) {
					used[to] = true; q.push(to);
				}
			}
		}
		if (cur < cnt)ans.push_back('1');
		else if (cur > cnt)ans.push_back('0');
		cur = cnt;
		//cout << "??? " << cnt << "\n";
	}
	cout << ans.size() << "\n";
	cout << ans << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();

	//int t; cin >> t; rep(i, t)
	while (cin >> n, n)solve();
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 36372
final_rank: 17

code_snippet: #include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
#include<cassert>
#include<set>
#include<complex>
using namespace std;
typedef long long int LL;
typedef pair<int,int> P;
typedef pair<LL,int> LP;
const int INF=1<<30;
const LL MAX=1e9+7;

void array_show(int *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}

void init(){
    
}

class Circle{
    typedef long double type;
    const type eps=1e-9;
public:
    complex<type> point;
    type r;

    Circle(type pa,type pb,type _r):point(pa,pb),r(_r){}

    vector<complex<type>> colision_point(Circle cir){
        complex<type> point2=cir.point;
        type r2=cir.r;
        vector<complex<type>> vs;
        if(abs(point2-point)>r+r2+eps || abs(point2-point)<abs(r-r2)-eps)return vs;
        complex<type> ca,cb;
        type da,db;
        ca=point2-point;
        da=r/abs(ca);
        ca*=da;
        if(abs(point2-point)>r+r2-eps || abs(point2-point)<abs(r-r2)+eps){
            vs.push_back(point+ca);
            return vs;
        }
        db=abs(point2-point);//dis
        da=(db*db+r*r-r2*r2)/(2*db*r);//cos
        cb.real(da),cb.imag(sqrt(1-da*da));
        vs.push_back(point+ca*cb);
        vs.push_back(point+ca/cb);
        return vs;
    }
};

class union_find_tree{
private:
    static constexpr int uft_N=100005;
    int uft_n;
    queue<int> uft_q1;
    vector<int> uft_parent;
    vector<int> uft_num;
public:
    void init(){
        uft_parent.assign(uft_n,-1);
        uft_num.assign(uft_n,1);
    }
    union_find_tree(int uft_n_init){
        assert(uft_n_init>=0);
        uft_n=uft_n_init;
        init();
    }
    union_find_tree(){
        uft_n=uft_N;
        init();
    }

    int check_parent(int uft_x){
        assert(uft_x>=0 && uft_x<uft_n);
        if(uft_parent[uft_x]!=-1){
            uft_q1.push(uft_x);
            return check_parent(uft_parent[uft_x]);
        }
        int uft_a;
        while(!uft_q1.empty()){
            uft_a=uft_q1.front(),uft_q1.pop();
            uft_parent[uft_a]=uft_x;
        }
        return uft_x;
    }

    bool connect(int uft_x,int uft_y){
        assert(uft_x>=0 && uft_x<uft_n);
        assert(uft_y>=0 && uft_y<uft_n);
        uft_x=check_parent(uft_x),uft_y=check_parent(uft_y);
        if(uft_x==uft_y)return true;
        if(uft_num[uft_x]>uft_num[uft_y])swap(uft_x,uft_y);
        uft_parent[uft_x]=uft_y;
        uft_num[uft_y]+=uft_num[uft_x];
        return false;
    }

    int size(int pos){
        pos=check_parent(pos);
        return uft_num[pos];
    }
};

long double t[200][4];

int main(){
    int n,m;
    int i,j,k;
    int a,b,c;
    while(cin>>n){
        if(n==0)break;
        for(i=0;i<n;i++){
            for(j=0;j<4;j++){
                cin>>t[i][j];
            }
        }
        vector<long double> v1;
        long double da,db;
        const long double eps=1e-9;
        for(i=0;i<n;i++){
            v1.push_back(t[i][2]-t[i][3]);
            v1.push_back(t[i][2]+t[i][3]);
            for(j=i+1;j<n;j++){
                da=t[j][0]-t[i][0],db=t[j][1]-t[i][1];
                Circle ca(0,t[i][2],t[i][3]);
                Circle cb(sqrt(da*da+db*db),t[j][2],t[j][3]);
                vector<complex<long double>> vs=ca.colision_point(cb);
                for(auto pt:vs){
                    v1.push_back(pt.imag());
                }
            }
        }
        int bef=0;
        string ss;
        sort(v1.begin(),v1.end());
        for(auto z:v1){
            union_find_tree ua(n);
            z+=eps;
            for(i=0;i<n;i++){
                if(z<t[i][2]-t[i][3] || t[i][2]+t[i][3]<z)continue;
                for(j=i+1;j<n;j++){
                    if(z<t[j][2]-t[j][3] || t[j][2]+t[j][3]<z)continue;
                    da=pow(t[i][0]-t[j][0],2)+pow(t[i][1]-t[j][1],2);
                    db=sqrt(pow(t[i][3],2)-pow(t[i][2]-z,2))+sqrt(pow(t[j][3],2)-pow(t[j][2]-z,2));
                    if(da>pow(db,2))continue;
                    ua.connect(i,j);
                }
            }
            a=0;
            for(i=0;i<n;i++){
                if(z<t[i][2]-t[i][3] || t[i][2]+t[i][3]<z)continue;
                if(ua.check_parent(i)==i)a++;
            }
            if(a==bef)continue;
            if(a>bef)ss.push_back('1');
            else ss.push_back('0');
            bef=a;
        }
        cout<<ss.size()<<endl;
        cout<<ss<<endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3208
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

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

//const long double EPS = 1e-10;
//const long long INF = 1e18;
//const long double PI = acos(-1.0L);
//const ll mod = 1000000007;
using Real = double;
using Point = complex< Real >;
const Real EPS = 1e-8, PI = acos(-1);

inline bool eq(Real a, Real 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) {
  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());
}

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

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

Real get_angle(const Point &a, const Point &b, const Point &c) {
  const Point v(b - a), w(c - b);
  Real alpha = atan2(v.imag(), v.real()), beta = atan2(w.imag(), w.real());
  if(alpha > beta) swap(alpha, beta);
  Real theta = (beta - alpha);
  return min(theta, 2 * acos(-1) - theta);
}

namespace std {
  bool operator<(const Point &a, const Point &b) {
    return 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) {}

  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 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 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 = vector< Point >;
using Polygon = vector< Point >;
using Segments = vector< Segment >;
using Lines = vector< Line >;
using Circles = vector< Circle >;

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

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

// 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 p + (projection(l, p) - p) * 2.0;
}

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

bool intersect(const Line &l, const Line &m) {
  return abs(cross(l.b - l.a, m.b - m.a)) > EPS || abs(cross(l.b - l.a, m.b - l.a)) < EPS;
}

bool intersect(const Segment &s, const Point &p) {
  return ccw(s.a, s.b, p) == 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;
}

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

bool intersect(const Circle &c, const Line &l) {
  return distance(l, c.p) <= c.r + EPS;
}

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

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
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;
}

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

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A&lang=jp
int intersect(Circle c1, Circle c2) {
  if(c1.r < c2.r) swap(c1, c2);
  Real d = abs(c1.p - c2.p);
  if(c1.r + c2.r < d) return 4;
  if(eq(c1.r + c2.r, d)) return 3;
  if(c1.r - c2.r < d) return 2;
  if(eq(c1.r - c2.r, d)) return 1;
  return 0;
}

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);
  if(intersect(s, r)) return abs(r - p);
  return 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 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 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
pair< Point, Point > crosspoint(const Circle &c, const Line l) {
  Point pr = projection(l, c.p);
  Point e = (l.b - l.a) / abs(l.b - l.a);
  if(eq(distance(l, c.p), c.r)) return {pr, pr};
  double base = sqrt(c.r * c.r - norm(pr - c.p));
  return {pr - e * base, pr + e * base};
}

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

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_E
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));
  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 {p1, p2};
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_F
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
Lines tangent(Circle c1, Circle c2) {
  Lines ret;
  if(c1.r < c2.r) swap(c1, c2);
  Real g = norm(c1.p - c2.p);
  if(eq(g, 0)) return ret;
  Point u = (c2.p - c1.p) / sqrt(g);
  Point 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) {
  int n = (int) p.size();
  for(int i = 0; i < n; i++) {
    if(ccw(p[(i + n - 1) % n], p[i], p[(i + 1) % n]) == -1) return false;
  }
  return true;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A
Polygon convex_hull(Polygon &p) {
  int n = (int) p.size(), k = 0;
  if(n <= 2) return p;
  sort(p.begin(), p.end());
  vector< Point > ch(2 * n);
  for(int i = 0; i < n; ch[k++] = p[i++]) {
    while(k >= 2 && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
  }
  for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) {
    while(k >= t && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --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;
  for(int i = 0; i < Q.size(); i++) {
    Point a = Q[i] - p, b = Q[(i + 1) % Q.size()] - p;
    if(a.imag() > b.imag()) swap(a, b);
    if(a.imag() <= 0 && 0 < b.imag() && cross(a, b) < 0) in = !in;
    if(cross(a, b) == 0 && dot(a, b) <= 0) return ON;
  }
  return in ? IN : OUT;
}


// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1033
void merge_segments(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
vector< vector< int > > segment_arrangement(vector< Segment > &segs, vector< Point > &ps) {
  vector< 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(cross(p1, p2) == 0) continue;
      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++) {
    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
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) < 0) {
      ret.push_back(crosspoint(Line(now, nxt), l));
    }
  }
  return (ret);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_A
Real area2(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;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_H
Real area2(const Polygon &p, const Circle &c) {
  if(p.size() < 3) return 0.0;
  function< Real(Circle, Point, Point) > cross_area = [&](const Circle &c, const Point &a, const Point &b) {
    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(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));
    vector< Point > tot{a, u.first, u.second, b};
    for(int i = 0; i + 1 < tot.size(); i++) {
      ret += cross_area(c, tot[i], tot[i + 1]);
    }
    return ret;
  };
  Real A = 0;
  for(int i = 0; i < p.size(); i++) {
    A += cross_area(c, p[i], p[(i + 1) % p.size()]);
  }
  return A;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_B
Real convex_diameter(const Polygon &p) {
  int N = (int) p.size();
  int is = 0, js = 0;
  for(int i = 1; i < N; i++) {
    if(p[i].imag() > p[is].imag()) is = i;
    if(p[i].imag() < p[js].imag()) js = i;
  }
  Real maxdis = norm(p[is] - p[js]);

  int maxi, maxj, i, j;
  i = maxi = is;
  j = maxj = js;
  do {
    if(cross(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]) > maxdis) {
      maxdis = norm(p[i] - p[j]);
      maxi = i;
      maxj = j;
    }
  } while(i != is || j != js);
  return sqrt(maxdis);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_5_A
Real closest_pair(Points ps) {
  if(ps.size() <= 1) throw (0);
  sort(begin(ps), end(ps));

  auto compare_y = [&](const Point &a, const Point &b) {
    return imag(a) < imag(b);
  };
  vector< Point > beet(ps.size());
  const Real INF = 1e18;

  function< Real(int, int) > rec = [&](int left, int right) {
    if(right - left <= 1) return INF;
    int mid = (left + right) >> 1;
    auto x = real(ps[mid]);
    auto ret = min(rec(left, mid), rec(mid, right));
    inplace_merge(begin(ps) + left, begin(ps) + mid, begin(ps) + right, compare_y);
    int ptr = 0;
    for(int i = left; i < right; i++) {
      if(abs(real(ps[i]) - x) >= ret) continue;
      for(int j = 0; j < ptr; j++) {
        auto luz = ps[i] - beet[ptr - j - 1];
        if(imag(luz) >= ret) break;
        ret = min(ret, abs(luz));
      }
      beet[ptr++] = ps[i];
    }
    return ret;
  };
  return rec(0, (int) ps.size());
}

int N;
int x[105], y[105], z[105], r[105];
struct UnionFind {
    vector<int> par;
    vector<int> rank;
    vector<ll> Size;
    UnionFind(int n = 1) {
        init(n);
    }

    void init(int n = 1) {
        par.resize(n + 1); rank.resize(n + 1); Size.resize(n + 1);
        for (int i = 0; i <= n; ++i) par[i] = i, rank[i] = 0, Size[i] = 1;
    }

    int root(int x) {
        if (par[x] == x) {
            return x;
        }
        else {
            int r = root(par[x]);
            return par[x] = r;
        }
    }

    bool issame(int x, int y) {
        return root(x) == root(y);
    }

    bool merge(int x, int y) {
        x = root(x); y = root(y);
        if (x == y) return false;
        if (rank[x] < rank[y]) swap(x, y);
        if (rank[x] == rank[y]) ++rank[x];
        par[y] = x;
        Size[x] += Size[y];
        return true;
    }

    ll size(int x){
        return Size[root(x)];
    }
};

UnionFind uni;

int f(double Z) {
    Circles C;
    for(int i = 0; i < N; i++) {
        double dz = Z - z[i];
        if(r[i] * r[i] - dz * dz < 0) continue;
        double R = pow(r[i]*r[i]-dz*dz, 0.5);
        C.push_back(Circle(Point(x[i], y[i]), R));
    }
    int n = C.size();
    uni.init(n);
    int ret = n;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(uni.issame(i, j)) continue;
            if(intersect(C[i], C[j]) == 4) continue;
            uni.merge(i, j);
            ret--;
        }
    }
    return ret;
}

void solve() {
    for(int i = 0; i < N; i++) {
        cin >> x[i] >> y[i] >> z[i] >> r[i];
    }
    vector<double> Z;
    for(int i = 0; i < N; i++) {
        Z.push_back(z[i] + r[i]);
        Z.push_back(z[i] - r[i]);
        for(int j = 0; j < i; j++) {
            double dx = x[i] - x[j];
            double dy = y[i] - y[j];
            double delta = pow(dx*dx+dy*dy, 0.5);
            Circle C1(Point(0, z[i]), r[i]);
            Circle C2(Point(delta, z[j]), r[j]);
            if(intersect(C1, C2) != 2) continue;
            auto tmp = crosspoint(C1, C2);
            Z.push_back(tmp.first.imag());
            Z.push_back(tmp.second.imag());
        }
    }
    Z.push_back(-1);
    Z.push_back(40000);
    sort(Z.begin(), Z.end());
    vector<double> Z2;
    for(int i = 0; i < Z.size(); i++) {
        if(i > 0) {
            Z2.push_back((Z[i] + Z[i-1]) / 2);
        }
        Z2.push_back(Z[i]);
    }
    Z2.erase(unique(Z2.begin(), Z2.end()), Z2.end());
    swap(Z2, Z);
    /*
    for(auto tmp : Z) {
        cerr << tmp << " ";
    }
    cerr << endl;
    */
    vector<int> v;
    for(int i = 0; i < Z.size(); i++) {
        v.push_back(f(Z[i]));
        //cerr << Z[i] << " " << v.back() << endl;
    }
    v.erase(unique(v.begin(), v.end()), v.end());
    string S;
    for(int i = 1; i < v.size(); i++) {
        if(v[i] > v[i-1]) S.push_back('1');
        else S.push_back('0');
    }
    cout << S.size() << endl;
    cout << S << endl;
}

int main() {
    //cout.precision(10);
    while(cin >> N) {
        if(N == 0) break;
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3500
final_rank: 8

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

using ld = long double;
using point2d = complex<ld>;
using point3d = array<ld, 3>;

constexpr ld eps = 1e-8;

ld abs(point3d const& p) {
    return sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]);
}

point3d operator-(point3d a, point3d const& b) {
    for(int i = 0; i < 3; ++i) a[i] -= b[i];
    return a;
}

class union_find {
public:
    union_find(int n) : par(n, -1) {}

    int root(int x) {
        return par[x] < 0 ? x : par[x] = root(par[x]);
    }

    void unite(int x, int y) {
        x = root(x), y = root(y);
        if(x == y) return;
        if(par[x] < par[y]) swap(x, y);
        par[x] += par[y];
        par[y] = x;
    }

private:
    vector<int> par;
};

int main() {
    int n;
    while(cin >> n, n) {
        vector<point3d> p(n);
        vector<ld> r(n);
        for(int i = 0; i < n; ++i) {
            ld x, y, z;
            cin >> x >> y >> z >> r[i];
            p[i] = {{x, y, z}};
        }

        auto contains = [&] (int i, int j) { // j contains i ?
            if(r[i] > r[j]) return false;
            // j is bigger than i
            return abs(p[i] - p[j]) + r[i] <= r[j];
        };
        vector<bool> ban(n);
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) {
                if(i == j) continue;
                if(abs(p[i] - p[j]) < eps) { // center is same
                    if(r[i] == r[j]) { // same sphere
                        ban[i] = ban[i] || i > j;
                    } else {
                        ban[i] = ban[i] || contains(i, j);
                    }
                } else {
                    ban[i] = ban[i] || contains(i, j);
                }
            }
        }

        vector<ld> zs;
        for(int i = 0; i < n; ++i) {
            if(ban[i]) continue;
            zs.push_back(p[i][2] - r[i]);
            zs.push_back(p[i][2] + r[i]);
            for(int j = i + 1; j < n; ++j) {
                if(ban[j]) continue;
                const ld d = abs(p[i] - p[j]);
                if(d >= r[i] + r[j]) continue;
                const auto v1 = point2d(p[j][0], p[j][1]) - point2d(p[i][0], p[i][1]);
                const ld phi = arg(v1);
                const auto pj_x = real(point2d(p[i][0], p[i][1]) + v1 * exp(point2d(0, -phi)));
                const ld d1 = (r[i] * r[i] - r[j] * r[j] + d * d) / 2 / d;
                const ld theta = acos(d1 / r[i]);
                const auto v2 = point2d(pj_x, p[j][2]) - point2d(p[i][0], p[i][2]);
                zs.push_back(imag(point2d(p[i][0], p[i][2]) + v2 / abs(v2) * exp(point2d(0, -theta)) * r[i]));
                zs.push_back(imag(point2d(p[i][0], p[i][2]) + v2 / abs(v2) * exp(point2d(0, theta)) * r[i]));
            }
        }
        sort(begin(zs), end(zs));
        {
            vector<ld> zzs;
            for(auto z : zs) {
                if(zzs.empty() || (z - zzs.back()) > eps) {
                    zzs.push_back(z);
                }
            }
            zs = move(zzs);
        }

        string ans;
        int prev = 0;
        for(int i = 0; i < (int)zs.size() - 1; ++i) {
            const ld z = (zs[i + 1] + zs[i]) / 2;
            vector<ld> r2(n);
            for(int j = 0; j < n; ++j) {
                if(r[j] - abs(p[j][2] - z) < eps) continue;
                r2[j] = sqrt(r[j] * r[j] - abs(p[j][2] - z) * abs(p[j][2] - z));
            }
            union_find uf(n);
            for(int j = 0; j < n; ++j) {
                if(r2[j] == 0) continue;
                for(int k = j + 1; k < n; ++k) {
                    if(r2[k] == 0) continue;
                    if(abs(point2d(p[j][0], p[j][1]) - point2d(p[k][0], p[k][1])) < r2[j] + r2[k]) {
                        uf.unite(j, k);
                    }
                }
            }
            set<int> s;
            for(int j = 0; j < n; ++j) {
                if(r2[j] == 0) continue;
                s.insert(uf.root(j));
            }
            if(prev != (int)s.size()) {
                ans += (prev < (int)s.size() ? '1' : '0');
            }
            prev = s.size();
        }
        ans += '0';

        cout << ans.size() << endl;
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3448
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

#define EPS (1e-8)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define PI 3.141592653589793238
 
// COUNTER CLOCKWISE
static const int CCW_COUNTER_CLOCKWISE = 1;
static const int CCW_CLOCKWISE = -1;
static const int CCW_ONLINE_BACK = 2;
static const int CCW_ONLINE_FRONT = -2;
static const int CCW_ON_SEGMENT = 0;

//Intercsect Circle & Circle
static const int ICC_SEPERATE = 4;
static const int ICC_CIRCUMSCRIBE = 3;
static const int ICC_INTERSECT = 2;
static const int ICC_INSCRIBE = 1;
static const int ICC_CONTAIN = 0;

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 norm(){return x*x+y*y;}
  double abs(){return sqrt(norm());}

  bool operator < (const Point &p) const{
    return x!=p.x?x<p.x:y<p.y;
    //grid-point only
    //return !equals(x,p.x)?x<p.x:!equals(y,p.y)?y<p.y:0;
  }

  bool operator == (const Point &p) const{
    return fabs(x-p.x)<EPS && fabs(y-p.y)<EPS;
  }
};

struct EndPoint{
  Point p;
  int seg,st;
  EndPoint(){}
  EndPoint(Point p,int seg,int st):p(p),seg(seg),st(st){}
  bool operator<(const EndPoint &ep)const{
    if(p.y==ep.p.y) return st<ep.st;
    return p.y<ep.p.y;
  }
};

istream &operator >> (istream &is,Point &p){
  is>>p.x>>p.y;
  return is;
}

ostream &operator << (ostream &os,Point p){
  os<<fixed<<setprecision(12)<<p.x<<" "<<p.y;
  return os;
}

bool sort_x(Point a,Point b){
  return a.x!=b.x?a.x<b.x:a.y<b.y;
}

bool sort_y(Point a,Point b){
  return a.y!=b.y?a.y<b.y:a.x<b.x;
}

typedef Point Vector;
typedef vector<Point> Polygon;

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

struct Segment{
  Point p1,p2;
  Segment(){}
  Segment(Point p1, Point p2):p1(p1),p2(p2){}
};
typedef Segment Line;

istream &operator >> (istream &is,Segment &s){
  is>>s.p1>>s.p2;
  return is;
}

struct Circle{
  Point c;
  double r;
  Circle(){}
  Circle(Point c,double r):c(c),r(r){}
};

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

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

Point orth(Point p){return Point(-p.y,p.x);}

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

double arg(Vector p){
  return atan2(p.y,p.x);
}

Vector polar(double a,double r){
  return Point(cos(r)*a,sin(r)*a);
}

int ccw(Point p0,Point p1,Point p2);
bool intersectSS(Point p1,Point p2,Point p3,Point p4);
bool intersectSS(Segment s1,Segment s2);
bool intersectPS(Polygon p,Segment l);
int intersectCC(Circle c1,Circle c2);
bool intersectSC(Segment s,Circle c);
double getDistanceLP(Line l,Point p);
double getDistanceSP(Segment s,Point p);
double getDistanceSS(Segment s1,Segment s2);
Point getCrossPointSS(Segment s1,Segment s2);
Point getCrossPointLL(Line l1,Line l2);
Polygon getCrossPointCL(Circle c,Line l);
Polygon getCrossPointCC(Circle c1,Circle c2);
int contains(Polygon g,Point p);
Polygon andrewScan(Polygon s);
Polygon convex_hull(Polygon ps);
double diameter(Polygon s);
bool isConvex(Polygon p);
double area(Polygon s);
Polygon convexCut(Polygon p,Line l);
Line bisector(Point p1,Point p2);
Vector translate(Vector v,double theta);
vector<Line> corner(Line l1,Line l2);
vector<vector<pair<int, double> > >
segmentArrangement(vector<Segment> &ss, Polygon &ps);
  
int ccw(Point p0,Point p1,Point p2){
  Vector a = p1-p0;
  Vector b = p2-p0;
  if(cross(a,b) > EPS) return CCW_COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS) return CCW_CLOCKWISE;
  if(dot(a,b) < -EPS) return CCW_ONLINE_BACK;
  if(a.norm()<b.norm()) return CCW_ONLINE_FRONT;
  return CCW_ON_SEGMENT;
}

bool intersectSS(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 intersectSS(Segment s1,Segment s2){
  return intersectSS(s1.p1,s1.p2,s2.p1,s2.p2);
}

bool intersectPS(Polygon p,Segment l){
  int n=p.size();
  for(int i=0;i<n;i++)
    if(intersectSS(Segment(p[i],p[(i+1)%n]),l)) return 1;
  return 0;
}

int intersectCC(Circle c1,Circle c2){
  if(c1.r<c2.r) swap(c1,c2);
  double d=abs(c1.c-c2.c);
  double r=c1.r+c2.r;
  if(equals(d,r)) return ICC_CIRCUMSCRIBE;
  if(d>r) return ICC_SEPERATE;
  if(equals(d+c2.r,c1.r)) return ICC_INSCRIBE;
  if(d+c2.r<c1.r) return ICC_CONTAIN;
  return ICC_INTERSECT;
}

bool intersectSC(Segment s,Circle c){
  return getDistanceSP(s,c.c)<=c.r;
}

int intersectCS(Circle c,Segment s){
  if(norm(project(s,c.c)-c.c)-c.r*c.r>EPS) return 0;
  double d1=abs(c.c-s.p1),d2=abs(c.c-s.p2);
  if(d1<c.r+EPS&&d2<c.r+EPS) return 0;
  if((d1<c.r-EPS&&d2>c.r+EPS)||(d1>c.r+EPS&&d2<c.r-EPS)) return 1;
  Point h=project(s,c.c);
  if(dot(s.p1-h,s.p2-h)<0) return 2;
  return 0;
}

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 getDistanceSS(Segment s1,Segment s2){
  if(intersectSS(s1,s2)) return 0.0;
  return min(min(getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2)),
             min(getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2)));
}

Point getCrossPointSS(Segment s1,Segment s2){
  for(int k=0;k<2;k++){
    if(getDistanceSP(s1,s2.p1)<EPS) return s2.p1; 
    if(getDistanceSP(s1,s2.p2)<EPS) return s2.p2;
    swap(s1,s2);
  }
  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 getCrossPointLL(Line l1,Line l2){
  double a=cross(l1.p2-l1.p1,l2.p2-l2.p1);
  double b=cross(l1.p2-l1.p1,l1.p2-l2.p1);
  if(abs(a)<EPS&&abs(b)<EPS) return l2.p1;
  return l2.p1+(l2.p2-l2.p1)*(b/a);
}

Polygon getCrossPointCL(Circle c,Line l){
  Polygon ps;
  Point pr=project(l,c.c);
  Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
  if(equals(getDistanceLP(l,c.c),c.r)){
    ps.emplace_back(pr);
    return ps;
  }
  double base=sqrt(c.r*c.r-norm(pr-c.c));
  ps.emplace_back(pr+e*base);
  ps.emplace_back(pr-e*base);
  return ps;
}

Polygon getCrossPointCS(Circle c,Segment s){
  Line l(s);
  Polygon res=getCrossPointCL(c,l);
  if(intersectCS(c,s)==2) return res;
  if(res.size()>1u){
    if(dot(l.p1-res[0],l.p2-res[0])>0) swap(res[0],res[1]);
    res.pop_back();
  }
  return res;
}


Polygon getCrossPointCC(Circle c1,Circle c2){
  Polygon p(2);
  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);
  p[0]=c1.c+polar(c1.r,t+a);
  p[1]=c1.c+polar(c1.r,t-a);
  return p;
}


struct UnionFind{
  int n;
  vector<int> r,p;
  UnionFind(){}
  UnionFind(int sz):n(sz),r(sz,1),p(sz,0){iota(p.begin(),p.end(),0);}
  int find(int x){
    return (x==p[x]?x:p[x]=find(p[x]));
  }
  bool same(int x,int y){
    return find(x)==find(y);
  }
  void unite(int x,int y){
    x=find(x);y=find(y);
    if(x==y) return;
    if(r[x]<r[y]) swap(x,y);
    r[x]+=r[y];
    p[y]=x;
  }
};

//INSERT ABOVE HERE
signed main(){
  int n;
  while(cin>>n,n){
    vector<double> xs(n),ys(n),zs(n),rs(n);
    for(int i=0;i<n;i++) cin>>xs[i]>>ys[i]>>zs[i]>>rs[i];

    const double EPS2 = 1e-5;
    vector<double> ds;
    for(int i=0;i<n;i++){
      ds.emplace_back(zs[i]-EPS);
      ds.emplace_back(zs[i]+EPS);
      ds.emplace_back(zs[i]-rs[i]-EPS2);
      ds.emplace_back(zs[i]-rs[i]+EPS2);
      ds.emplace_back(zs[i]+rs[i]-EPS2);
      ds.emplace_back(zs[i]+rs[i]+EPS2);
    }
    ds.emplace_back(0);
    ds.emplace_back(36000);

    for(int i=0;i<n;i++){
      for(int j=0;j<i;j++){
        double d=abs(Point(xs[i],ys[i])-Point(xs[j],ys[j]));
        Point a(0,zs[i]),b(d,zs[j]);
        Circle p(a,rs[i]),q(b,rs[j]);
        if(intersectCC(p,q)!=ICC_INTERSECT) continue;
        auto cs=getCrossPointCC(p,q);
        for(auto c:cs){
          //cout<<i<<" "<<j<<":"<<c.y<<endl;
          ds.emplace_back(c.y-EPS2);
          ds.emplace_back(c.y+EPS2);
        }
      }
    }
    
    sort(ds.begin(),ds.end());
    ds.erase(unique(ds.begin(),ds.end()),ds.end());
    
    vector<int> cnt;
    for(auto d:ds){
      UnionFind uf(n);
      int res=n;
      vector<Circle> cs(n);
      for(int i=0;i<n;i++){
        double a=abs(d-zs[i]);
        if(a>rs[i]){
          cs[i]=Circle(Point(xs[i],ys[i]),-1);
          res--;
          continue;
        }
        double r=sqrt(rs[i]*rs[i]-a*a);
        cs[i]=Circle(Point(xs[i],ys[i]),r);
      }
      for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
          if(uf.same(i,j)) continue;
          if(cs[i].r<0||cs[j].r<0) continue;
          if(abs(cs[i].c-cs[j].c)<cs[i].r+cs[j].r) uf.unite(i,j),res--;
        }        
      }
      cnt.emplace_back(res);
      //cout<<d<<":"<<res<<endl;
    }
    
    cnt.erase(unique(cnt.begin(),cnt.end()),cnt.end());
    cout<<cnt.size()-1<<endl;
    for(int i=0;i+1<(int)cnt.size();i++) cout<<(cnt[i]<cnt[i+1]);
    cout<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 3836
final_rank: 13

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class t>
using table = vector<vector<t>>;
const ld eps = 1e-9;
#include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;

struct Point3 {
	long double x;
	long double y;
	long double z;
	Point3() :x(0), y(0), z(0) {}
	Point3(const long double _x, const long double _y, const long double _z) :x(_x), y(_y), z(_z) {}
};

Point3 operator+(const Point3&l, const Point3& r) {
	return Point3(l.x + r.x, l.y + r.y, l.z + r.z);
}
Point3 operator+=(Point3&l, const Point3& r) {
	return l = Point3(l.x + r.x, l.y + r.y, l.z + r.z);
}
Point3 operator-(const Point3&l, const Point3& r) {
	return Point3(l.x - r.x, l.y - r.y, l.z - r.z);
}
Point3 operator-=(Point3&l, const Point3& r) {
	return l = Point3(l.x - r.x, l.y - r.y, l.z - r.z);
}
Point3 operator*(const Point3&l, const long double r) {
	return Point3(l.x * r, l.y * r, l.z * r);
}
Point3 operator*(const long double r, const Point3&l) {
	return l*r;
}
Point3 operator*=(Point3&l, const long double r) {
	return l = Point3(l.x * r, l.y * r, l.z * r);
}
Point3 operator/(const Point3&l, const long double r) {
	return Point3(l.x / r, l.y / r, l.z / r);
}
Point3 operator/=(Point3&l, const long double r) {
	return l = Point3(l.x / r, l.y / r, l.z / r);
}
const long double  pi = acos(-1.0);
const long double dtop = pi / 180.;
const long double ptod = 1. / dtop;

namespace std {
	bool operator<(const Point3 &lhs, const Point3 &rhs) {
		if (lhs.x< rhs.x - eps) return true;
		if (lhs.x > rhs.x + eps) return false;
		if (lhs.y< rhs.y - eps) return true;
		if (lhs.y > rhs.y + eps) return false;
		return lhs.z < rhs.z;
	}
}

// ????????\???
Point3 input_point() {
	long double x, y, z;
	cin >> x >> y >> z;
	return Point3(x, y, z);
}

// ????????????????????????
bool eq(const long double a, const long double b) {
	return (abs(a - b) < eps);
}

// ??????
long double dot(const Point3& a, const Point3& b) {
	return a.x*b.x + a.y*b.y + a.z*b.z;
}

// ??????
Point3 cross(const Point3& a, const Point3& b) {
	return Point3(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x);
}



//?????????
long double norm(const Point3&p) {
	return (p.x*p.x + p.y*p.y + p.z*p.z);
}

long double abs(const Point3&p) {

	return sqrt(p.x*p.x + p.y*p.y + p.z*p.z);
}
//?????????????????????
Point3 unit(const Point3& a) {
	return a / (abs(a));
}




//???
struct Sphere {
	Point3 p;
	long double r;
	Sphere() :p(), r(0) {}
	Sphere(const Point3 _point, const long double _radius) :p(_point), r(_radius) {}
};
/*  0 => out
1 => on
2 => in*/
int point_in_sphere(const Point3&p, const Sphere&s) {
	ld dis = abs(s.p - p);
	if (dis - eps > s.r)return 0;
	else if (dis + eps < s.r)return 2;
	else return 1;
}

//a ??? b ?????\??£????????????
int sphere_in_sphere(const Sphere&a, const Sphere&b) {
	if (!point_in_sphere(a.p, b))return 0;
	else {
		ld dis = abs(a.p - b.p);
		if (a.r + dis - eps>b.r)return 0;
		else if (a.r + dis + eps < b.r)return 2;
		else return 1;
	}
}

// ??´????????????
class Line3 {
public:
	Point3 a, b;
	Line3() : a(Point3(0, 0, 0)), b(Point3(0, 0, 0)) {}
	Line3(Point3 a, Point3 b) : a(a), b(b) {}
	Point3 operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else assert(false);
	}
};

// ?????????????????????
bool isis_sp(const Line3& s, const Point3& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// ??????????¶?
Point3 proj(const Line3 &l, const Point3& p) {
	long double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + t * (l.a - l.b);
}
// ??´?????¨???????????¢
long double dist_lp3(const Line3& l, const Point3& p) {
	return abs(p - proj(l, p));
}
// ?????¨??´????????????
vector<Point3> is_lsp(const Sphere& c, const Line3& l) {
	vector<Point3> res;
	long double d = dist_lp3(l, c.p);
	if (d < c.r + eps) {
		long double len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point3 nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}
// ?????¨???????????????
vector<Point3> is_ssp(const Sphere& c, const Line3& l) {
	vector<Point3> res(is_lsp(c, l));
	vector<Point3> nres;
	for (auto p : res) {
		if (isis_sp(l, p))nres.emplace_back(p);
	}
	return nres;
}
// ????????????????????¢(??????)??§???????°?
Point3 reflect(const Point3& vec, const Point3& no) {
	return vec - 2 * dot(vec, no) / abs(no)*unit(no);

}


struct UnionFind {
	vector<int> data;
	UnionFind(int size) : data(size, -1) { }
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	bool findSet(int x, int y) {
		return root(x) == root(y);
	}
	int root(int x) {
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	int size(int x) {
		return -data[root(x)];
	}
};


// a binary predicate implemented as a function:
bool same_integral_part(double first, double second)
{
	return (abs((first)-(second))<eps);
}

int main() {
	while (1) {

		int N; cin >> N;
		if (!N)break;
		vector<Sphere>sps;
		for (int i = 0; i < N; ++i) {

			ld x, y, z, r; cin >> x >> y >> z >> r;
			Sphere sp(Point3(x, y, z), r);
			sps.emplace_back(sp);
		}
		vector<ld>nums;
		for (int i = 0; i < N; ++i) {
			for (int j = i + 1; j < N; ++j) {
				ld aminz, amaxz;
				if (sphere_in_sphere(sps[i], sps[j])) {
				}
				else if (sphere_in_sphere(sps[j], sps[i])) {
				}
				else {
					ld dis = abs(sps[j].p - sps[i].p);
					Point3 center = (sps[i].p + sps[j].p) / 2;

					if (dis - eps > sps[j].r + sps[i].r)continue;
					else {

						{
							ld amin = max(sps[i].p.z - sps[i].r, sps[j].p.z - sps[j].r) + eps;
							ld amax = ((sps[i].p.z + sps[j].p.z) - (sps[i].p.z - sps[j].p.z) * (sps[i].r - sps[j].r) / dis) / 2.0;

							int num = 50;
							ld disxy = sqrt(powl(sps[i].p.x - sps[j].p.x, 2) + powl(sps[i].p.y - sps[j].p.y, 2));
							while (num--) {
								ld amid = (amin + amax) / 2;
								ld ir = sqrt(sps[i].r*sps[i].r - powl(sps[i].p.z - amid, 2));
								ld jr = sqrt(powl(sps[j].r, 2) - powl(sps[j].p.z - amid, 2));
								if (ir + jr < disxy) {
									amin = amid;
								}
								else {
									amax = amid;
								}
							}
							aminz = amin;
						}
						{
							ld amax = min(sps[i].p.z + sps[i].r, sps[j].p.z + sps[j].r) + eps;
							ld amin = ((sps[i].p.z + sps[j].p.z) - (sps[i].p.z - sps[j].p.z) * (sps[i].r - sps[j].r) / dis) / 2.0;

							int num = 50;
							ld disxy = sqrt(powl(sps[i].p.x - sps[j].p.x, 2) + powl(sps[i].p.y - sps[j].p.y, 2));
							while (num--) {
								ld amid = (amin + amax) / 2;
								ld ir = sqrt(sps[i].r*sps[i].r - powl(sps[i].p.z - amid, 2));
								ld jr = sqrt(powl(sps[j].r, 2) - powl(sps[j].p.z - amid, 2));
								if (ir + jr > disxy) {
									amin = amid;
								}
								else {
									amax = amid;
								}
							}
							amaxz = amax;
						}
						
					}
				}
				nums.emplace_back(aminz);
				nums.emplace_back(amaxz);
				
			}
			nums.emplace_back(sps[i].p.z - sps[i].r);
			nums.emplace_back(sps[i].p.z + sps[i].r);
		}
		nums.emplace_back(-1);
		nums.emplace_back(100000);
		sort(nums.begin(), nums.end());
		nums.erase(unique(nums.begin(), nums.end(), same_integral_part),nums.end());

		vector<int>anss;
		for (int i = 0; i < nums.size()-1; ++i) {
			ld az = (nums[i] + nums[i + 1]) / 2;
			UnionFind uf(N);
			vector<int>valids(N);
			for (int j = 0; j < N; ++j) {
				if (az >= sps[j].p.z- sps[j].r&&az <= sps[j].p.z + sps[j].r)valids[j] = true;
			}
			for (int j = 0; j < N; ++j)
			{
				for (int k = j+1; k < N; ++k) {
					if (valids[j] && valids[k]) {
						ld disxy = sqrt(powl(sps[k].p.x - sps[j].p.x, 2) + powl(sps[k].p.y - sps[j].p.y, 2));

						ld kr = sqrt(sps[k].r*sps[k].r - powl(sps[k].p.z - az, 2));
						ld jr = sqrt(powl(sps[j].r, 2) - powl(sps[j].p.z - az, 2));
						if (kr + jr > disxy) {
							uf.unionSet(j, k);
						}
						else {
						}
					}
				}
			}
			set<int>aset;
			for (int j = 0; j < N; ++j) {
				if (valids[j])aset.emplace(uf.root(j));
			}
			anss.emplace_back(aset.size());
		}
		string st;
		for (int i = 0; i < anss.size() - 1; ++i) {
			if (anss[i + 1] == anss[i] + 1)st += '1';
			else if (anss[i + 1] + 1 == anss[i])st += '0';

		}
		cout << st.size() << endl << st << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3532
final_rank: 12

code_snippet: #include<iostream>
#include<vector>
#include<numeric>
#include<algorithm>
#include<cmath>

using namespace std;

int par[123];
int x[123],y[123],z[123],r[123];

int find(int x){
  return (par[x]==x)?x:par[x]=find(par[x]);
}

void unite(int a,int b){
  par[find(a)]=find(b);
}

double sqr(double d){
  return d*d;
}

double dist(int i,int j,double zz){
  return sqrt(r[i]*r[i]-sqr(z[i]-zz))+sqrt(r[j]*r[j]-sqr(z[j]-zz));
}

double cross(int i,int j,double bm){
  double d=dist(i,j,bm);
  return sqr(x[i]-x[j])+sqr(y[i]-y[j])-d*d<0;
}

int main(){
  for(int n;cin>>n,n;){
    vector<double> cz{0,1e9};
    for(int i=0;i<n;i++){
      cin>>x[i]>>y[i]>>z[i]>>r[i];
      cz.push_back(z[i]+r[i]);
      cz.push_back(z[i]-r[i]);
      for(int j=0;j<i;j++){
	if(sqr(x[i]-x[j])+sqr(y[i]-y[j])+sqr(z[i]-z[j])<sqr(r[i]+r[j])){
	  int rl=max(z[i]-r[i],z[j]-r[j]),rh=min(z[i]+r[i],z[j]+r[j]);
	  double l=rl,h=rh;
	  for(int k=0;k<99;k++){
	    double lh=(h-l)/3+l,hl=(h-l)*2/3+l;
	    if(dist(i,j,lh)<dist(i,j,hl)){
	      l=lh;
	    }else{
	      h=hl;
	    }
	  }
	  double bl=rl,bh=l;
	  double tl=l,th=rh;
	  for(int k=0;k<99;k++){
	    double bm=(bh+bl)/2;
	    if(cross(i,j,bm)){
	      bh=bm;
	    }else{
	      bl=bm;
	    }
	    double tm=(tl+th)/2;
	    if(cross(i,j,tm)){
	      tl=tm;
	    }else{
	      th=tm;
	    }
	  }
	  //	  cout<<rl<<' '<<l<<' '<<rh<<' '<<bl<<' '<<tl<<endl;
	  cz.push_back(bl);
	  cz.push_back(tl);
	}
      }
    }
    sort(begin(cz),end(cz));
    vector<int> ns{0};
    for(int i=0;i<cz.size()-1;i++){
      double m=(cz[i]+cz[i+1])/2;
      iota(begin(par),end(par),0);
      for(int i=0;i<n;i++){
	if(r[i]*r[i]>sqr(z[i]-m)){
	  for(int j=0;j<i;j++){
	    if(r[j]*r[j]>sqr(z[j]-m)&&cross(i,j,m)){
	      unite(i,j);
	    }
	  }
	}else{
	  par[i]=-1;
	}
      }
      bool u[123]={};
      int ncs=0;
      for(int i=0;i<n;i++){
	if(par[i]>=0){
	  ncs+=!u[find(i)]++;
	}
      }
      //      cout<<m<<' '<<ncs<<endl;
      if(ncs!=ns.back()){
	ns.push_back(ncs);
      }
    }
    cout<<ns.size()-1<<endl;
    for(int i=0;i<ns.size()-1;i++){
      cout<<(ns[i+1]-ns[i]==1);
    }
    cout<<endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 1228
final_rank: 3

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <algorithm>
#include <cstring>
#include <functional>
#include <cmath>
#include <complex>
#include <cassert>
using namespace std;
#define rep(i,n) for(int i=0;i<(n);++i)
#define rep1(i,n) for(int i=1;i<=(n);++i)
#define all(c) (c).begin(),(c).end()
#define fs first
#define sc second
#define pb push_back
#define show(x) cout << #x << " " << x << endl
int N;
double x[100],y[100],z[100],r[100];
vector<double> zs;
double sq(double a,double b){return (a-b)*(a-b);}
double dist(int a,int b){return sqrt(sq(x[a],x[b])+sq(y[a],y[b])+sq(z[a],z[b]));}
int par[100];
void init(int N){rep(i,N) par[i]=i;}
int find(int x){
	if(x==par[x]) return x;
	return par[x]=find(par[x]);
}
void unite(int x,int y){
	x=find(x),y=find(y);
	par[x]=y;
}
int cut(double a){
	double rr[100]={};
	bool is[100]={};
	rep(i,N) if(z[i]-r[i]<a&&a<z[i]+r[i]){
		is[i]=1;
		rr[i]=sqrt(r[i]*r[i]-sq(z[i],a));
	}
	init(N);
	rep(i,N) rep(j,i){
		if(!is[i]||!is[j]) continue;
		if(sqrt(sq(x[i],x[j])+sq(y[i],y[j]))<rr[i]+rr[j]) unite(i,j);
	}
	set<int> ps;
	rep(i,N) if(is[i]) ps.insert(find(i));
	return ps.size();
}
int main(){
	while(true){
		cin>>N;
		if(N==0) break;
		zs.clear();
		rep(i,N) cin>>x[i]>>y[i]>>z[i]>>r[i];
		rep(i,N) zs.pb(z[i]-r[i]),zs.pb(z[i]+r[i]);
		rep(i,N) rep(j,i){
			double d=dist(i,j);
			if(d>r[i]+r[j]) continue;
			if(abs(r[i]-r[j])>d) continue;
			double theta=acos( (r[i]*r[i]+d*d-r[j]*r[j])/(2.0*r[i]*d) );
			double phi=atan2( z[j]-z[i],sqrt(sq(x[i],x[j])+sq(y[i],y[j])) );
			zs.pb(z[i]+r[i]*sin(theta+phi));
			zs.pb(z[i]+r[i]*sin(-theta+phi));
		}
		sort(all(zs));
		int now=0;
		string ans;
		for(double a:zs){
			int t=cut(a+1e-4);
			if(t==now+1){
				ans+='1';
			}else if(t==now-1){
				ans+='0';
			}else if(t==now){
			}else{
				assert(0);
			}
			now=t;
		}
		cout<<ans.size()<<endl<<ans<<endl;
	}
}
accuracy: 1
time_ms: 20
memory_kb: 1416
final_rank: 4

code_snippet: #include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
double event[1000000];
double x[200];
double y[200];
double z[200];
double r[200];
double dist(double x1,double y1,double z1,double x2,double y2,double z2){
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
}
double Abs(double a){return max(a,-a);}
const double EPS=1e-10;
const double INF=1e+10;
const double PI=acos(-1);
int sig(double r){return (r<-EPS)?-1:(r>+EPS)?+1:0;}
struct Pt{
	double x,y;
	Pt(){}
	Pt(double x,double y):x(x),y(y){}
	Pt operator+(const Pt &a)const{return Pt(x+a.x,y+a.y);}
	Pt operator-(const Pt &a)const{return Pt(x-a.x,y-a.y);}
	Pt operator*(const Pt &a)const{return Pt(x*a.x-y*a.y,x*a.y+y*a.x);}
	Pt operator-()const{return Pt(-x,-y);}
	Pt operator*(const double &k)const{return Pt(x*k,y*k);}
	Pt operator/(const double &k)const{return Pt(x/k,y/k);}
	double Abs()const{return sqrt(x*x+y*y);}
	double Abs2()const{return x*x+y*y;}
	double arg()const{return atan2(y,x);}
	double dot(const Pt &a)const{return x*a.x+y*a.y;}
	double det(const Pt &a)const{return x*a.y-y*a.x;}
};
double tri(const Pt&a,const Pt&b,const Pt&c){return (b-a).det(c-a);}
pair<Pt,Pt> pCC(Pt a,double r,Pt b,double s){
	double d=(b-a).Abs();
	double x=(d*d+r*r-s*s)/(d*2);
	Pt e=(b-a)/d,w=e*Pt(0,1)*sqrt(max(r*r-x*x,0.0));
	return make_pair(a+e*x-w,a+e*x+w);
}
int ans[100000];
int UF[128];
int FIND(int a){
	if(UF[a]<0)return a;
	return UF[a]=FIND(UF[a]);
}
void UNION(int a,int b){
	a=FIND(a);b=FIND(b);
	if(a==b)return;
	UF[a]+=UF[b];
	UF[b]=a;
}
int main(){
	int a;
	while(scanf("%d",&a),a){
		for(int i=0;i<a;i++)scanf("%lf%lf%lf%lf",x+i,y+i,z+i,r+i);
		int ind=0;
		event[ind++]=0;
		for(int i=0;i<a;i++){
			event[ind++]=z[i]-r[i];
			event[ind++]=z[i]+r[i];
		}
		for(int i=0;i<a;i++)
			for(int j=i+1;j<a;j++){
				if(dist(x[i],y[i],z[i],x[j],y[j],z[j])>r[i]+r[j])continue;
				if(Abs(r[i]-r[j])>dist(x[i],y[i],z[i],x[j],y[j],z[j]))continue;
				pair<Pt,Pt> inter=pCC(Pt(0.0,z[i]),r[i],Pt(dist(x[i],y[i],0,x[j],y[j],0),z[j]),r[j]);
				event[ind++]=inter.first.y;
				event[ind++]=inter.second.y;
			}
		event[ind++]=50000;
		std::sort(event,event+ind);
		int at=0;
		int last=0;
		for(int i=0;i<ind;i++){
			if(i&&event[i]-event[i-1]<EPS)continue;
			double M=(event[i]+event[i-1])/2;
			for(int j=0;j<a;j++)UF[j]=-1;
			for(int j=0;j<a;j++){
				if(M+EPS<z[j]-r[j]||M-EPS>z[j]+r[j])continue;
				for(int k=j+1;k<a;k++){
					if(M+EPS<z[k]-r[k]||M-EPS>z[k]+r[k])continue;
					if(dist(x[j],y[j],0,x[k],y[k],0)<sqrt(r[j]*r[j]-(z[j]-M)*(z[j]-M))+sqrt(r[k]*r[k]-(z[k]-M)*(z[k]-M)))UNION(j,k);
				}
			}
			int count=0;
			for(int j=0;j<a;j++){
				if(M+EPS<z[j]-r[j]||M-EPS>z[j]+r[j])continue;
				//printf("(%d,%d) ",j,UF[j]);
				if(UF[j]<0)count++;
			}
			if(last!=count){
				if(last<count)ans[at++]=1;
				else ans[at++]=0;
			}
		//	printf("%f %d\n",M,count);
			last=count;
		}
		printf("%d\n",at);
		for(int i=0;i<at;i++)printf("%d",ans[i]);
		printf("\n");
	}
}
accuracy: 1
time_ms: 10
memory_kb: 1104
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <complex>
#include <cmath>
#include <iterator>
using namespace std;
typedef complex<double> P;
static const double EPS = 1e-6;

struct P3
{
  double x, y, z;
  P3() {}
  P3(double a, double b, double c) : x(a), y(b), z(c) {}
  P3& operator+=(const P3& q) { x += q.x; y += q.y; z += q.z; return *this; }
  P3& operator-=(const P3& q) { x -= q.x; y -= q.y; z -= q.z; return *this; }
  P3& operator*=(double a) { x *= a; y *= a; z *= a; return *this; }
  P3& operator/=(double a) { x /= a; y /= a; z /= a; return *this; }

};
inline ostream& operator<<(ostream& os, const P3& p) { return os << "(" << p.x << "," << p.y << "," << p.z << ")"; }
P3 operator+(const P3& p, const P3& q) { P3 r(p); return r += q; }
P3 operator-(const P3& p, const P3& q) { P3 r(p); return r -= q; }
P3 operator*(const P3& p, double a) { P3 q(p); q *= a; return q; }
P3 operator*(double a, const P3& p) { return p*a; }
P3 operator/(const P3& p, double a) { P3 q(p); q /= a; return q; }
P3 operator/(double a, const P3& p) { return p/a; }
inline double dot(const P3& p, const P3& q) { return p.x*q.x + p.y*q.y + p.z*q.z; }
inline double abs(const P3& p) { return sqrt(dot(p, p)); }
inline P3 cross(const P3& p, const P3& q) { return P3(p.y*q.z - q.y*p.z, p.z*q.x - q.z*p.x, p.x*q.y - q.x*p.y); }

struct circle
{
  P o;
  double r;
  circle() {}
  circle(const P& p, double x) : o(p), r(x) {}

  inline bool contains(const circle& c) const { return abs(o - c.o)+c.r <= r; }
  inline bool intersects(const circle& c) const { return !contains(c) && !c.contains(*this) && abs(o - c.o) <= r + c.r; }
  pair<P,P> intersection(const circle& c) const
  {
    // assert(intersects(c))
    const double d = abs(o - c.o);
    const double cos_ = (d*d + r*r - c.r*c.r) / (2*d);
    const double sin_ = sqrt(r*r - cos_*cos_);
    const P e = (c.o - o) / d;
    return make_pair(o + e*P(cos_, sin_), o + e*P(cos_, -sin_));
  }
};
inline ostream& operator<<(ostream& os, const circle& c) { return os << c.o << "[r=" << c.r << "]"; }

struct sphere
{
  P3 o;
  double r;
  sphere(const P3& p, double x) : o(p), r(x) {}

  inline circle cutz(double z) const { return circle(P(o.x, o.y), sqrt(r*r - (z-o.z)*(z-o.z))); }
  inline bool contains(const sphere& s) const { return abs(o - s.o)+s.r <= r; }
  inline bool intersects(const sphere& s) const { return !contains(s) && !s.contains(*this) && abs(o - s.o) <= r + s.r; }

  double center_z(const sphere& s) const
  {
    const P3 p = s.o - o;
    const double L = abs(p);
    const double x1 = (r*r - s.r*s.r + L*L)/(2*L);
    return (o + x1/L*p).z;
  }

  pair<double,double> intersection_z(const sphere& that) const
  {
    const double z0 = center_z(that);
    double left = z0, right = min(o.z+r, that.o.z+that.r);
    for (int i = 0; i < 100; i++) {
      const double mid = (left+right)/2.0;
      const circle c1 = cutz(mid), c2 = that.cutz(mid);
      const double d = abs(c1.o - c2.o);
      if (d < c1.r + c2.r) {
        left = mid;
      } else {
        right = mid;
      }
    }
    const double z1 = (left+right)/2.0;

    left = max(o.z-r, that.o.z-that.r), right = z0;
    for (int i = 0; i < 100; i++) {
      const double mid = (left+right)/2.0;
      const circle c1 = cutz(mid), c2 = that.cutz(mid);
      const double d = abs(c1.o - c2.o);
      if (d < c1.r + c2.r) {
        right = mid;
      } else {
        left = mid;
      }
    }
    const double z2 = (left+right)/2.0;
    return make_pair(z1, z2);
  }
};
inline ostream& operator<<(ostream& os, const sphere& s) { return os << s.o << "[r=" << s.r << "]"; }

struct DisjointSet/*{{{*/
{
  vector<int> parent;

  int root(int x)
  {
    if (parent[x] < 0) {
      return x;
    } else {
      parent[x] = root(parent[x]);
      return parent[x];
    }
  }

  explicit DisjointSet(int n) : parent(n, -1) {}

  bool unite(int x, int y)
  {
    const int a = root(x);
    const int b = root(y);
    if (a != b) {
      if (parent[a] < parent[b]) {
        parent[a] += parent[b];
        parent[b] = a;
      } else {
        parent[b] += parent[a];
        parent[a] = b;
      }
      return true;
    } else {
      return false;
    }
  }

  bool find(int x, int y) { return root(x) == root(y); }
  int size(int x) { return -parent[root(x)]; }
};/*}}}*/

int count_sphere(const vector<sphere>& ss, double z)
{
  vector<circle> cs;
  for (vector<sphere>::const_iterator it = ss.begin(); it != ss.end(); ++it) {
    if (abs(z - it->o.z) < it->r) {
      cs.push_back(it->cutz(z));
    }
  }

  const int N = cs.size();
  DisjointSet s(N);
  for (int i = 0; i < N; i++) {
    for (int j = i+1; j < N; j++) {
      if (cs[i].contains(cs[j]) || cs[j].contains(cs[i]) || cs[i].intersects(cs[j])) {
        s.unite(i, j);
      }
    }
  }
  int ans = 0;
  for (int i = 0; i < N; i++) {
    if (s.parent[i] < 0) {
      ++ans;
    }
  }
  return ans;
}

int main()
{
  int N;
  while (cin >> N && N != 0) {
    vector<sphere> ss;
    vector<double> zs;
    for (int i = 0; i < N; i++) {
      int x, y, z, r;
      cin >> x >> y >> z >> r;
      ss.push_back(sphere(P3(x, y, z), r));
      zs.push_back(z-r);
      zs.push_back(z+r);
    }

    for (vector<sphere>::const_iterator it = ss.begin(); it != ss.end(); ++it) {
      for (vector<sphere>::const_iterator jt = it+1; jt != ss.end(); ++jt) {
        if (it->intersects(*jt)) {
          const pair<double,double> r = it->intersection_z(*jt);
          zs.push_back(r.first);
          zs.push_back(r.second);
        }
      }
    }
    sort(zs.begin(), zs.end());

    vector<char> ans;
    int prev = 0;
    for (vector<double>::const_iterator it = zs.begin(); it != zs.end(); ++it) {
      const int r = count_sphere(ss, *it+EPS);
      if (prev < r) {
        ans.push_back('1');
      } else if (prev > r) {
        ans.push_back('0');
      }
      prev = r;
    }

    cout << ans.size() << endl;
    copy(ans.begin(), ans.end(), ostream_iterator<char>(cout, ""));
    cout << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1

code_snippet: #include<iostream>
#include<complex>
#include<algorithm>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define pb         push_back
#define mp         make_pair

const double eps = 1e-10;

typedef complex<double> P;

class Point{
public:
  double x,y,z;
};
/*
for live archive
bool isnan(double x){
  if (x >=0 || x <= 0)return false;
  return true;
}
*/
class DisjointSet{
public:
  vector<int> rank,p;
  DisjointSet(){}
  DisjointSet(int size){
    rank.resize(size,0);
    p.resize(size,0);
  }
  
  void makeset(int x){
    p[x]=x;
    rank[x]=0;
  }
  void merge(int x,int y){
    link(findset(x),findset(y));
  }

  void link(int x,int y){
    if (rank[x] > rank[y]){
      p[y]=x;
    }else {
      p[x]=y;
      if (rank[x] == rank[y])rank[y]++;
    }
  }
  int findset(int x){
    if (x != p[x])p[x] = findset(p[x]);
    return p[x];
  }
};

int is_intersected_circle(P a,P b,double r1,double r2){
  double d =abs(a-b);
  if (d<eps&&abs(r1-r2)<eps)return 3;
  if (d+r2 < r1)return 0;
  if (d+r1 < r2)return 1;

  if (d > r1+r2)return 4;

  return 2;
}

inline double calc_r(double z,double r){
  if (z < 0)z*=-1;
  return sqrt(r*r-z*z);
}

double bsearch(P a,P b,double az,double bz,double ar,double br,double r,double l,
	       bool islower){
  double mid;
  while(l < r+eps){
    mid = (r+l)/2;
    if (islower){
      if (is_intersected_circle(a,b,calc_r(az-mid,ar),calc_r(bz-mid,br))==2)r=mid-eps;
      else l=mid+eps;
    }else {
      if (is_intersected_circle(a,b,calc_r(az-mid,ar),calc_r(bz-mid,br))==2)l=mid+eps;
      else r=mid-eps;
    }
  }
  return mid;
}

int is_intersected_sphere(Point a,Point b,double r1,double r2){
  double d =sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
  if (d<eps&&abs(r1-r2)<eps)return 3;
  if (d+r2 < r1)return 0;
  if (d+r1 < r2)return 1;
  if (d > r1+r2)return 4;
  return 2;
}

double compute_z(Point a,Point b,double r1,double r2){
  double l,m,n;
  double d =sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)); 
  double z;
  l=(d*d-r2*r2+r1*r1)/(2*d);
  z = a.z + (b.z-a.z)*l/d;
  return z;
}

bool is_contain_center_in_circle(P a,P b,double r1){
  if (isnan(r1))return false;
  double d = abs(a-b);
  if (d < r1 + eps)return true;
  return false;
}

bool is_contain_on_intersection(P a,P b,double ra,double rb){
   return is_contain_center_in_circle(a,b,ra)||is_contain_center_in_circle(b,a,rb);
}

void solve(int n,Point *in,double *r){
  vector<pair<double,int> > ans;
  rep(i,n){
    ans.pb(mp(in[i].z-r[i],1));
    ans.pb(mp(in[i].z+r[i],0));
  }

  rep(i,n){
    REP(j,i+1,n){
      int tmp = is_intersected_sphere(in[i],in[j],r[i],r[j]);
      if (is_intersected_sphere(in[i],in[j],r[i],r[j]) == 2){
	double z = compute_z(in[i],in[j],r[i],r[j]);
	double right,left;
	right=z;
	left=max(in[i].z-r[i],in[j].z-r[j]);
	double tmp =bsearch(P(in[i].x,in[i].y),P(in[j].x,in[j].y),in[i].z,in[j].z,
			    r[i],r[j],right,left,true); 
	ans.pb(mp(tmp,1));//start of intersection
	right=min(in[i].z+r[i],in[j].z+r[j]);
	left=z;
	tmp = bsearch(P(in[i].x,in[i].y),P(in[j].x,in[j].y),in[i].z,in[j].z,
		      r[i],r[j],right,left,false);
	ans.pb(mp(tmp,0));//start of intersection
      }
    }
  }


  int component=0;
  sort(ALL(ans));
  DisjointSet dj(n);
  vector<int >ret;
  rep(k,ans.size()){
    int tmp=0;
    double z = ans[k].first+eps;
    rep(i,n)dj.makeset(i);
    rep(i,n){
      if (isnan(calc_r(in[i].z-z,r[i])))continue;
      REP(j,i+1,n){
	if (isnan(calc_r(in[j].z-z,r[j])))continue;	
	if (
	    is_contain_on_intersection(
				       P(in[i].x,in[i].y),
				       P(in[j].x,in[j].y),
				       calc_r(in[i].z-z,r[i]),
				       calc_r(in[j].z-z,r[j]))
	    ||
	    is_intersected_circle(P(in[i].x,in[i].y),
				  P(in[j].x,in[j].y),
				  calc_r(in[i].z-z,r[i]),
				  calc_r(in[j].z-z,r[j])) == 2
	    
	    )dj.merge(i,j);
      }
    }
 
    rep(i,n){
      if (isnan(calc_r(in[i].z-z,r[i])))continue;
      if (i == dj.findset(i))tmp++;
    }
    
    if (tmp > component)ret.pb(1);//cout << 1;
    else if (tmp < component)ret.pb(0);//cout << 0;
    component=tmp;
  }

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


main(){
  int n;
  while(cin>>n && n){
    double r[n];
    Point in[n];
    rep(i,n){
      cin>>in[i].x>>in[i].y>>in[i].z >>r[i];
    }
    solve(n,in,r);
  }
}
accuracy: 1
time_ms: 720
memory_kb: 1008
final_rank: 15

code_snippet: #include<iostream>
#include<complex>
#include<algorithm>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define pb         push_back
#define mp         make_pair

const double eps = 1e-10;

typedef complex<double> P;

class Point{
public:
  double x,y,z;
};

class DisjointSet{
public:
  vector<int> rank,p;
  DisjointSet(){}
  DisjointSet(int size){
    rank.resize(size,0);
    p.resize(size,0);
  }
  
  void makeset(int x){
    p[x]=x;
    rank[x]=0;
  }
  void merge(int x,int y){
    link(findset(x),findset(y));
  }

  void link(int x,int y){
    if (rank[x] > rank[y]){
      p[y]=x;
    }else {
      p[x]=y;
      if (rank[x] == rank[y])rank[y]++;
    }
  }
  int findset(int x){
    if (x != p[x])p[x] = findset(p[x]);
    return p[x];
  }
};

int is_intersected_circle(P a,P b,double r1,double r2){
  double d =abs(a-b);
  if (d<eps&&abs(r1-r2)<eps)return 3;
  if (d+r2 < r1)return 0;
  if (d+r1 < r2)return 1;

  if (d > r1+r2)return 4;

  return 2;
}

inline double calc_r(double z,double r){
  if (z < 0)z*=-1;
  return sqrt(r*r-z*z);
}

double bsearch(P a,P b,double az,double bz,double ar,double br,double r,double l,
	       bool islower){
  double mid;
  while(l < r+eps){
    mid = (r+l)/2;
    if (islower){
      if (is_intersected_circle(a,b,calc_r(az-mid,ar),calc_r(bz-mid,br))==2)r=mid-eps;
      else l=mid+eps;
    }else {
      if (is_intersected_circle(a,b,calc_r(az-mid,ar),calc_r(bz-mid,br))==2)l=mid+eps;
      else r=mid-eps;
    }
  }
  return mid;
}

int is_intersected_sphere(Point a,Point b,double r1,double r2){
  double d =sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
  if (d<eps&&abs(r1-r2)<eps)return 3;
  if (d+r2 < r1)return 0;
  if (d+r1 < r2)return 1;
  if (d > r1+r2)return 4;
  return 2;
}

double compute_z(Point a,Point b,double r1,double r2){
  double l,m,n;
  double d =sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)); 
  double z;
  l=(d*d-r2*r2+r1*r1)/(2*d);
  z = a.z + (b.z-a.z)*l/d;
  return z;
}

bool is_contain_center_in_circle(P a,P b,double r1){
  if (isnan(r1))return false;
  double d = abs(a-b);
  if (d < r1 + eps)return true;
  return false;
}

bool is_contain_on_intersection(P a,P b,double ra,double rb){
   return is_contain_center_in_circle(a,b,ra)||is_contain_center_in_circle(b,a,rb);
}

void solve(int n,Point *in,double *r){
  vector<pair<double,int> > ans;
  rep(i,n){
    ans.pb(mp(in[i].z-r[i],1));
    ans.pb(mp(in[i].z+r[i],0));
  }

  rep(i,n){
    REP(j,i+1,n){
      int tmp = is_intersected_sphere(in[i],in[j],r[i],r[j]);
      if (is_intersected_sphere(in[i],in[j],r[i],r[j]) == 2){
	double z = compute_z(in[i],in[j],r[i],r[j]);
	double right,left;
	right=z;
	left=max(in[i].z-r[i],in[j].z-r[j]);
	double tmp =bsearch(P(in[i].x,in[i].y),P(in[j].x,in[j].y),in[i].z,in[j].z,
			    r[i],r[j],right,left,true); 
	ans.pb(mp(tmp,1));//start of intersection
	right=min(in[i].z+r[i],in[j].z+r[j]);
	left=z;
	tmp = bsearch(P(in[i].x,in[i].y),P(in[j].x,in[j].y),in[i].z,in[j].z,
		      r[i],r[j],right,left,false);
	ans.pb(mp(tmp,0));//start of intersection
      }
    }
  }


  int component=0;
  sort(ALL(ans));
  DisjointSet dj(n);
  vector<int >ret;
  rep(k,ans.size()){
    int tmp=0;
    double z = ans[k].first+eps;
    rep(i,n)dj.makeset(i);
    rep(i,n){
      if (isnan(calc_r(in[i].z-z,r[i])))continue;
      REP(j,i+1,n){
	if (isnan(calc_r(in[j].z-z,r[j])))continue;	
	if (
	    is_contain_on_intersection(
				       P(in[i].x,in[i].y),
				       P(in[j].x,in[j].y),
				       calc_r(in[i].z-z,r[i]),
				       calc_r(in[j].z-z,r[j]))
	    ||
	    is_intersected_circle(P(in[i].x,in[i].y),
				  P(in[j].x,in[j].y),
				  calc_r(in[i].z-z,r[i]),
				  calc_r(in[j].z-z,r[j])) == 2
	    
	    )dj.merge(i,j);
      }
    }
 
    rep(i,n){
      if (isnan(calc_r(in[i].z-z,r[i])))continue;
      if (i == dj.findset(i))tmp++;
    }
    
    if (tmp > component)ret.pb(1);//cout << 1;
    else if (tmp < component)ret.pb(0);//cout << 0;
    component=tmp;
  }

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


main(){
  int n;
  while(cin>>n && n){
    double r[n];
    Point in[n];
    rep(i,n){
      cin>>in[i].x>>in[i].y>>in[i].z >>r[i];
    }
    solve(n,in,r);
  }
}
accuracy: 1
time_ms: 710
memory_kb: 1008
final_rank: 14

code_snippet: #include<iostream>
#include<complex>
#include<algorithm>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define pb         push_back
#define mp         make_pair

const double eps = 1e-10;

typedef complex<double> P;

class Point{
public:
  double x,y,z;
};

class DisjointSet{
public:
  vector<int> rank,p;
  DisjointSet(){}
  DisjointSet(int size){
    rank.resize(size,0);
    p.resize(size,0);
  }
  
  void makeset(int x){
    p[x]=x;
    rank[x]=0;
  }
  void merge(int x,int y){
    link(findset(x),findset(y));
  }

  void link(int x,int y){
    if (rank[x] > rank[y]){
      p[y]=x;
    }else {
      p[x]=y;
      if (rank[x] == rank[y])rank[y]++;
    }
  }
  int findset(int x){
    if (x != p[x])p[x] = findset(p[x]);
    return p[x];
  }
};

int is_intersected_circle(P a,P b,double r1,double r2){
  double d =abs(a-b);
  if (d<eps&&abs(r1-r2)<eps)return 3;
  if (d+r2 < r1)return 0;
  if (d+r1 < r2)return 1;

  if (d > r1+r2)return 4;

  return 2;
}

inline double calc_r(double z,double r){
  if (z < 0)z*=-1;
  return sqrt(r*r-z*z);
}



double bsearch(P a,P b,double az,double bz,double ar,double br,double r,double l,
	       bool islower){
  double mid;
  while(l < r+eps){
    mid = (r+l)/2;
    if (islower){
      if (is_intersected_circle(a,b,calc_r(az-mid,ar),calc_r(bz-mid,br))==2)r=mid-eps;
      else l=mid+eps;
    }else {
      if (is_intersected_circle(a,b,calc_r(az-mid,ar),calc_r(bz-mid,br))==2)l=mid+eps;
      else r=mid-eps;
    }
  }
  return mid;
}

int is_intersected_sphere(Point a,Point b,double r1,double r2){
  double d =sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
  if (d<eps&&abs(r1-r2)<eps)return 3;
  if (d+r2 < r1)return 0;
  if (d+r1 < r2)return 1;
  if (d > r1+r2)return 4;
  return 2;
}

double compute_z(Point a,Point b,double r1,double r2){
  double l,m,n;
  double d =sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)); 
  double z;
  l=(d*d-r2*r2+r1*r1)/(2*d);
  z = a.z + (b.z-a.z)*l/d;
  return z;
}

bool is_contain_center_in_sphere(Point a,Point b,double r1){
  double d =sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)); 
  if (d < r1+eps)return true;
  return false;
}

bool is_contain_center_in_circle(P a,P b,double r1){
  if (isnan(r1))return false;
  double d = abs(a-b);
  if (d < r1 + eps)return true;
  return false;
}

bool is_contain_on_intersection(P a,P b,double ra,double rb){
   return is_contain_center_in_circle(a,b,ra)||is_contain_center_in_circle(b,a,rb);
}

void solve(int n,Point *in,double *r){
  vector<pair<double,int> > ans;
  rep(i,n){
    ans.pb(mp(in[i].z-r[i],1));
    ans.pb(mp(in[i].z+r[i],0));
  }

  rep(i,n){
    REP(j,i+1,n){
      int tmp = is_intersected_sphere(in[i],in[j],r[i],r[j]);
      if (is_intersected_sphere(in[i],in[j],r[i],r[j]) == 2){
	double z = compute_z(in[i],in[j],r[i],r[j]);
	double right,left;
	right=z;
	left=max(in[i].z-r[i],in[j].z-r[j]);
	double tmp =bsearch(P(in[i].x,in[i].y),P(in[j].x,in[j].y),in[i].z,in[j].z,
			    r[i],r[j],right,left,true); 
	ans.pb(mp(tmp,1));//start of intersection
	right=min(in[i].z+r[i],in[j].z+r[j]);
	left=z;
	tmp = bsearch(P(in[i].x,in[i].y),P(in[j].x,in[j].y),in[i].z,in[j].z,
		      r[i],r[j],right,left,false);
	ans.pb(mp(tmp,0));//start of intersection
      }
    }
  }


  int component=0;
  sort(ALL(ans));
  DisjointSet dj(n);
  vector<int >ret;
  rep(k,ans.size()){
    int tmp=0;
    double z = ans[k].first+eps;
    rep(i,n)dj.makeset(i);

    //cout <<k <<" " << z <<" " << ans[k].second <<  endl;



    rep(i,n){
      if (isnan(calc_r(in[i].z-z,r[i])))continue;
      REP(j,i+1,n){
	if (isnan(calc_r(in[j].z-z,r[j])))continue;	
	if (
	    is_contain_on_intersection(
				       P(in[i].x,in[i].y),
				       P(in[j].x,in[j].y),
				       calc_r(in[i].z-z,r[i]),
				       calc_r(in[j].z-z,r[j]))
	    ||
	    is_intersected_circle(P(in[i].x,in[i].y),
				  P(in[j].x,in[j].y),
				  calc_r(in[i].z-z,r[i]),
				  calc_r(in[j].z-z,r[j])) == 2
	    
	    )dj.merge(i,j);
      }
    }
    
    rep(i,n){
      if (isnan(calc_r(in[i].z-z,r[i])))continue;
      if (i == dj.findset(i))tmp++;
    }

    /*
      rep(i,n){
      if (isnan(calc_r(in[i].z-z,r[i])))cout <<"= ";
      else cout << dj.findset(i) <<" ";
    }
    cout << endl;
    */    

    
    if (tmp > component)ret.pb(1);//cout << 1;
    else if (tmp < component)ret.pb(0);//cout << 0;
    

    component=tmp;
  }

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

      /*
  sort(ALL(ans));
  cout << ans.size() << endl;
  rep(i,ans.size()){
    cout << ans[i].second;
  }
  cout << endl;
      */
}


main(){
  int n;
  while(cin>>n && n){
    double r[n];
    Point in[n];
    rep(i,n){
      cin>>in[i].x>>in[i].y>>in[i].z >>r[i];
    }
    solve(n,in,r);
  }
}
accuracy: 1
time_ms: 720
memory_kb: 1008
final_rank: 15