Problem:
KND Warp
Problem
KND君は会津大学に在籍する学生プログラマだ。彼はその優秀な頭脳をもってワープ装置を開発したことで有名である。ワープ装置とは便利なもので、ある場所から別の場所まで瞬時に移動することができる。彼はこれから地球上に点在するワープ装置を用いて様々な場所を可能な限り早くめぐる旅を計画している。
彼の隣人であるあなたの仕事は3次元空間 (xyz直交座標系) 上に存在する
N
個のワープ装置をうまく使用して、1から
M
までの番号がふられた
M
個の点を順に通って、
M
番目の点まで移動するときの最小の所要時間を求めることだ。はじめは1番目の点にいるものとし、どのワープ装置も任意のワープ装置へ時間0で移動できる。ワープ以外の単位距離の移動は単位時間を要する。経由点のクエリは
Q
個与えられる。
Input
入力は複数のテストケースからなる。
ひとつのテストケースは以下の形式で与えられる。
入力の終わりを
N
=
Q
= 0のとき示す。
N
Q
x
1
y
1
z
1
x
2
y
2
z
2
...
x
N
y
N
z
N
M
1
x
1,1
y
1,1
z
1,1
x
1,2
y
1,2
z
1,2
...
x
1,M
y
1,M
z
1,M
M
2
x
2,1
y
2,1
z
2,1
x
2,2
y
2,2
z
2,2
...
x
2,M
y
2,M
z
2,M
...
M
Q
x
Q,1
y
Q,1
z
Q,1
x
Q,2
y
Q,2
z
Q,2
...
x
Q,M
y
Q,M
z
Q,M
ここで、
N
:ワープ装置の数
Q
:旅のクエリの数
M
i
:i番目クエリの旅で訪れる点の数
x
i,j
,
y
i,j
,
z
i,j
:i番目のクエリの旅で訪れるj番目の点の座標(x,y,z)
である。
Constraints
入力は以下の条件を満たす。
テストケースの数は15個を超えない。
入力の半分程度は
N
≤1000を満たす。
入力に含まれる値はすべて整数。
2≤
N
≤100,000
1≤
Q
≤1,000
2≤
M
≤100
-1,000,000≤(全てのx,y,z座標値)≤1,000,000
ワープ装置は上記の制約を満たす空間中にランダムに分布する(Sample Inputは例外)。
ワープ装置同士、中継点同士、ワープ装置と中継点はそれぞれ重なることがある。
Output
各クエリにつき最小の所要時間を一行に出力せよ。この値はジャッジ出力の値と10
-4
より大きい差を持ってはならない。
Sample Input
3 2
0 0 0
1 1 1
2 2 2
4
-1 -1 -1
3 3 3
-1 -1 -1
4 4 4
2
1234 5678 9012
1716 6155 9455
0 0
Sample Output
12.124355653
810.001234567
Notes
入力ファイルのサイズは4MB程度になる。入力は高速にしたほうがよいが、たとえばC++であればcinでも十分である。

Submitted solutions:

code_snippet: // AOJ #1094 KND Warp
// 2025.3.7

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

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {  // 整数の入力
	int n = 0, c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

struct P { int x, y, z; };
struct N { int x, y, z, l, r; };

vector<N> T;
vector<P> W;

int build(int s, int e, int d, vector<int>& idx) {
    if(s > e) return -1;
    int m = (s+e)/2, dm = d % 3;
    auto cmp = [&](int a, int b) {
        if(dm==0) return W[a].x < W[b].x;
        if(dm==1) return W[a].y < W[b].y;
        return W[a].z < W[b].z;
    };
    nth_element(idx.begin()+s, idx.begin()+m, idx.begin()+e+1, cmp);
    int id = idx[m];
    N nd;
    nd.x = W[id].x; nd.y = W[id].y; nd.z = W[id].z;
    nd.l = nd.r = -1;
    int cur = T.size();
    T.push_back(nd);
    int L = build(s, m-1, d+1, idx);
    int R = build(m+1, e, d+1, idx);
    T[cur].l = L; T[cur].r = R;
    return cur;
}

void dfs(int i, int d, int qx, int qy, int qz, double &best) {
    if(i == -1) return;
    long long dx = qx - T[i].x, dy = qy - T[i].y, dz = qz - T[i].z;
    double dist = (double)dx*dx + (double)dy*dy + (double)dz*dz;
    if(dist < best) best = dist;
    int dm = d % 3;
    double diff = 0;
    if(dm==0) diff = qx - T[i].x;
    else if(dm==1) diff = qy - T[i].y;
    else diff = qz - T[i].z;
    int fst = (diff < 0 ? T[i].l : T[i].r);
    int snd = (diff < 0 ? T[i].r : T[i].l);
    dfs(fst, d+1, qx, qy, qz, best);
    if(diff*diff < best) dfs(snd, d+1, qx, qy, qz, best);
}

int main(){
    while(true){
        int n = Cin(), Q = Cin();
        if(n==0) break;

        W.resize(n);
        for (int i=0; i<n; i++) W[i].x = Cin(), W[i].y = Cin(), W[i].z = Cin();

        T.clear();
        vector<int> idx(n);
        for (int i=0; i<n; i++) idx[i] = i;
        int root = build(0, n-1, 0, idx);

        for (int i=0; i<Q; i++){
            int m = Cin();
            vector<P> p(m);
            for (int j=0; j<m; j++)
                p[j].x = Cin(), p[j].y = Cin(), p[j].z = Cin();

            double ans = 0.0;
            for (int j=0; j<m-1; j++){
                int ax = p[j].x, ay = p[j].y, az = p[j].z;
                int bx = p[j+1].x, by = p[j+1].y, bz = p[j+1].z;
                double dx = ax - bx, dy = ay - by, dz = az - bz;
                double d1 = sqrt(dx*dx + dy*dy + dz*dz);

                double bestA = 1e18;
                dfs(root, 0, ax, ay, az, bestA);
                double dA = sqrt(bestA);
                double bestB = 1e18;
                dfs(root, 0, bx, by, bz, bestB);
                double dB = sqrt(bestB);
                double d2 = dA + dB;
                ans += min(d1, d2);
            }
            printf("%.9lf\n", ans);
        }
    }
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 7264
final_rank: 1

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define LARGE 100005
#define SMALL 105

struct Point{

	bool operator<(const struct Point &arg)const{

		return x < arg.x;
	}
	double x,y,z;
};

int N,Q;
int M;
Point point[LARGE],work[SMALL];
double near_dist[SMALL];

double calc_dist(Point a,Point b){

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

void func(){

	for(int i = 0; i < N; i++){

		scanf("%lf %lf %lf",&point[i].x,&point[i].y,&point[i].z);
	}
	sort(point,point+N);

	for(int loop = 0; loop < Q; loop++){

		scanf("%d",&M);

		int left,right,mid,loc;

		for(int i = 0; i < M; i++){

			scanf("%lf %lf %lf",&work[i].x,&work[i].y,&work[i].z);

			near_dist[i] = HUGE_NUM;

			//自分より右にある点の中で、最も左にあるものを求める
			left = 0,right = N-1,mid = (left+right)/2;
			loc = N;

			while(left <= right){

				if(point[mid].x >= work[i].x){

					loc = mid;
					right = mid-1;
				}else{

					left = mid+1;
				}
				mid = (left+right)/2;
			}

			//右へ
			for(int k = loc; k < N && sqrt((work[i].x-point[k].x)*(work[i].x-point[k].x)) < near_dist[i]; k++){

				near_dist[i] = min(near_dist[i],calc_dist(work[i],point[k]));
			}

			//左へ
			for(int k = loc-1; k >= 0 && sqrt((work[i].x-point[k].x)*(work[i].x-point[k].x)) < near_dist[i]; k--){

				near_dist[i] = min(near_dist[i],calc_dist(work[i],point[k]));
			}
		}

		double ans = 0;

		for(int i = 0; i < M-1; i++){

			ans += min(calc_dist(work[i],work[i+1]),near_dist[i]+near_dist[i+1]);
		}

		printf("%.10lf\n",ans);
	}
}

int main(){

	while(true){
		scanf("%d %d",&N,&Q);
		if(N == 0 && Q == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 1940
memory_kb: 5628
final_rank: 11

code_snippet: // 参考: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=2137009#1
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <memory>  // unique_ptr
#include <cmath>
#include <iomanip>

#define REP(i, a, b) for (int i = int(a); i < int(b); i++)
#ifdef _DEBUG_
#define dump(val) cerr << __LINE__ << ":\t" << #val << " = " << (val) << endl
#else
#define dump(val)
#endif

using namespace std;

typedef long long int ll;

template<typename T>
vector<T> make_v(size_t a, T b) {
    return vector<T>(a, b);
}
template<typename... Ts>
auto make_v(size_t a, Ts... ts) {
    return vector<decltype(make_v(ts...))>(a, make_v(ts...));
}

template<class T>
class kdTree {
    using VV = vector<vector<T>>;
    vector<T> vec;
    int axis;
    unique_ptr<kdTree> ltree, rtree;
    void make_tree(VV &v, int l, int r, int depth = 0) {
        if (l >= r) return;
        int mid = (l + r) / 2;
        axis = depth % v[mid].size();
        auto cmp = [&](vector<T> &a, vector<T> &b) -> bool {
            return a[axis] < b[axis];
        };
        nth_element(v.begin() + l, v.begin() + mid, v.begin() + r, cmp);
        ltree = kdTree::get_tree(v, l, mid, depth + 1);
        rtree = kdTree::get_tree(v, mid + 1, r, depth + 1);
        vec = v[mid];
    }
    T dist(vector<T> &d1, vector<T> &d2) {
        T ans = T();
        REP(i, 0, d1.size()) {
            ans += pow(d1[i] - d2[i], 2.0);
        }
        return sqrt(ans);
    }
    static unique_ptr<kdTree> get_tree(VV &v, int l, int r, int depth) {
        if (l >= r) {
            return nullptr;
        } else {
            return make_unique<kdTree>(v, l, r, depth);
        }
    }
public:
    kdTree(VV &v): kdTree(v, 0, v.size(), 0) {}
    kdTree(VV &v, int l, int r, int depth) {
        make_tree(v, l, r, depth);
    }
    void nearest(vector<T> &query, double &ans) {
        ans = min(ans, dist(vec, query));
        if (query[axis] <= vec[axis]) {
            if (ltree) {
                ltree->nearest(query, ans);
            }
            if (vec[axis] - query[axis] >= ans) return;
            if (rtree) {
                rtree->nearest(query, ans);
            }
        } else {
            if (rtree) {
                rtree->nearest(query, ans);
            }
            if (query[axis] - vec[axis] >= ans) return;
            if (ltree) {
                ltree->nearest(query, ans);
            }
        }
    }
};

double dist(vector<double> &v1, vector<double> &v2) {
    double ans = 0.0;
    REP (i, 0, v1.size()) {
        ans += pow(v1[i] - v2[i], 2);
    }
    return sqrt(ans);
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, q;
    while (cin >> n >> q, n + q) {
        auto p = make_v(n, 3, 0.0);
        REP(i, 0, n) {
            REP(j, 0, 3) {
                cin >> p[i][j];
            }
        }
        kdTree<double> kdtree(p);
        REP(Q, 0, q) {
            int m;
            cin >> m;
            double ans = 0.0;
            vector<double> prev(3), curr(3);
            REP(i, 0, 3) {
                cin >> prev[i];
            }
            REP(i, 1, m) {
                REP (j, 0, 3) {
                    cin >> curr[j];
                }
                double ans1 = 1e+15, ans2 = 1e+15;
                kdtree.nearest(prev, ans1);
                kdtree.nearest(curr, ans2);
                ans += min(dist(curr, prev), ans1 + ans2);
                prev = curr;
            }
            cout << fixed << setprecision(10) << ans << endl;
        }
    }

    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 17664
final_rank: 7

code_snippet: // 参考: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=2137009#1
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <memory>  // unique_ptr
#include <cmath>
#include <iomanip>

#define REP(i, a, b) for (int i = int(a); i < int(b); i++)
#ifdef _DEBUG_
#define dump(val) cerr << __LINE__ << ":\t" << #val << " = " << (val) << endl
#else
#define dump(val)
#endif

using namespace std;

typedef long long int ll;

template<typename T>
vector<T> make_v(size_t a, T b) {
    return vector<T>(a, b);
}
template<typename... Ts>
auto make_v(size_t a, Ts... ts) {
    return vector<decltype(make_v(ts...))>(a, make_v(ts...));
}

template<class T>
class kdTree {
    public:
    vector<T> vec;
    int axis;
    unique_ptr<kdTree> ltree, rtree;
    void make_tree(vector<vector<T>> &v, int l, int r, int depth = 0) {
        if (l >= r) return;
        int mid = (l + r) / 2;
        axis = depth % v[mid].size();
        auto cmp = [&](vector<T> &a, vector<T> &b) -> bool {
            return a[axis] < b[axis];
        };
        nth_element(v.begin() + l, v.begin() + mid, v.begin() + r, cmp);
        if (l < mid) {
            ltree = make_unique<kdTree>(v, l, mid, depth + 1);
        }
        if (mid + 1 < r) {
            rtree = make_unique<kdTree>(v, mid + 1, r, depth + 1);
        }
        vec = v[mid];
    }
    T dist(vector<T> &d1, vector<T> &d2) {
        T ans = T();
        REP(i, 0, d1.size()) {
            ans += pow(d1[i] - d2[i], 2.0);
        }
        return sqrt(ans);
    }

public:
    kdTree(vector<vector<T>> &v): kdTree(v, 0, v.size(), 0) {}
    kdTree(vector<vector<T>> &v, int l, int r, int depth) {
        make_tree(v, l, r, depth);
    }
    void nearest(vector<T> &query, double &ans) {
        ans = min(ans, dist(vec, query));
        if (query[axis] <= vec[axis]) {
            if (ltree) {
                ltree->nearest(query, ans);
            }
            if (vec[axis] - query[axis] >= ans) return;
            if (rtree) {
                rtree->nearest(query, ans);
            }
        } else {
            if (rtree) {
                rtree->nearest(query, ans);
            }
            if (query[axis] - vec[axis] >= ans) return;
            if (ltree) {
                ltree->nearest(query, ans);
            }
        }
    }
};

double dist(vector<double> &v1, vector<double> &v2) {
    double ans = 0.0;
    REP (i, 0, v1.size()) {
        ans += pow(v1[i] - v2[i], 2);
    }
    return sqrt(ans);
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, q;
    while (cin >> n >> q, n + q) {
        auto p = make_v(n, 3, 0.0);
        REP(i, 0, n) {
            REP(j, 0, 3) {
                cin >> p[i][j];
            }
        }
        kdTree<double> kdtree(p);
        dump(kdtree.axis);
        REP(Q, 0, q) {
            int m;
            cin >> m;
            double ans = 0.0;
            vector<double> prev(3), curr(3);
            REP(i, 0, 3) {
                cin >> prev[i];
            }
            REP(i, 1, m) {
                REP (j, 0, 3) {
                    cin >> curr[j];
                }
                double ans1 = 1e+15, ans2 = 1e+15;
                kdtree.nearest(prev, ans1);
                kdtree.nearest(curr, ans2);
                ans += min(dist(curr, prev), ans1 + ans2);
                prev = curr;
            }
            cout << fixed << setprecision(10) << ans << endl;
        }
    }

    return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 17588
final_rank: 8

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


struct po {
	int index;
	vector<long long int> coors;
	po(int _d):coors(_d) {
		index = -1;
	}
	po(int index_, const vector<long long int>&coors_) :index(index_), coors(coors_) {

	}
	po() {}
};
template<class T>
class axisSorter {
	int k;
public:
	axisSorter(int _k) : k(_k) {}
	bool operator()(const T &a, const T &b) {
		return a.coors[k] < b.coors[k];
	}
};
long long int getdis(const po&l, const po&r) {
	long long int dis = 0;
	for (int i = 0; i < l.coors.size(); ++i) {
		dis += (l.coors[i] - r.coors[i])*(l.coors[i] - r.coors[i]);
	}
	return dis;
}
template<class T, int Dim = 3>
struct kdtree {
public:
	T val;
  shared_ptr<kdtree<T>> ltree, rtree;
	int depth;
	int axis;
	kdtree(const T &p_) :val(p_), ltree(nullptr), rtree(nullptr) {

	}

	kdtree(vector<T>&ps_, const int& l, const int& r, const int depth_ = 0) : ltree(nullptr), rtree(nullptr), depth(depth_), axis(depth%Dim) {
		init(ps_, l, r);
	}
	vector<T>query(const T & amin, const T&amax) {
		vector<T>ans;
		bool aok = true;
		for (int i = 0; i < Dim; ++i) {
			if (amin.coors[i] <= val.coors[i] && val.coors[i] <= amax.coors[i]) {

			}
			else {
				aok = false;
				break;
			}
		}
		if (aok) {
			ans.emplace_back(val);
		}
		axisSorter<T> as(axis);
		if (as(val, amax) || val.coors[axis] == amax.coors[axis]) {
			if (rtree != nullptr) {
				vector<T>tans(rtree->query(amin, amax));
				ans.insert(ans.end(), tans.begin(), tans.end());
			}
		}
		if (as(amin, val) || val.coors[axis] == amin.coors[axis]) {
			if (ltree != nullptr) {
				vector<T>tans(ltree->query(amin, amax));
				ans.insert(ans.end(), tans.begin(), tans.end());
			}
		}
		return ans;
	}
	void get_closest(const T& apo, long long int &ans) {
		ans = min(ans, getdis(apo, val));
		axisSorter<T> as(axis);
		if (as(apo, val) || val.coors[axis] == apo.coors[axis]) {
			if (ltree)ltree->get_closest(apo, ans);
			long long int dis = apo.coors[axis] - val.coors[axis];
			if (dis*dis >= ans)return;
			else {
				if (rtree)rtree->get_closest(apo, ans);
			}
		}
		else {
			if (rtree)rtree->get_closest(apo, ans);
			long long int dis = val.coors[axis] - apo.coors[axis];
			if (dis*dis >= ans)return;
			else {
				if (ltree)ltree->get_closest(apo, ans);
			}
		}
	}
private:
	void init(vector<T>&ps, const int& l, const int& r) {
		if (l >= r) {
			return;
		}
		const int mid = (l + r) / 2;
		nth_element(ps.begin() + l, ps.begin() + mid, ps.begin() + r, axisSorter<T>(axis));
		val = ps[mid];
		ltree = make_kdtree(ps, l, mid, depth + 1);
		rtree = make_kdtree(ps, mid + 1, r, depth + 1);
	}

};
//[l..r)
template<class T>
unique_ptr<kdtree<T>>make_kdtree(vector<T>&ps_, const int& l, const int& r, const int& depth = 0) {
	if (l >= r)return nullptr;
	else {
		return make_unique<kdtree<T>>(ps_, l, r, depth);
	}
}

int main() {
	cout << setprecision(10) << fixed;
	while (1) {
		int N, Q; cin >> N >> Q;
		if (!N)break;
		vector<po>pos;
		for (int i = 0; i < N; ++i) {
			int x, y, z; cin >> x >> y >> z;
			pos.push_back(po(i, vector<long long int>{x, y, z}));
		}
		int l = 0, r = N;
		kdtree<po>tree(pos,l,r);
		while (Q--) {

			int M; cin >> M;
			vector<po>points;
			for (int i = 0; i < M; ++i) {
				int x, y, z; cin >> x >> y >> z;
				po p(0, vector<long long int>{x, y, z});
				points.push_back(p);
			}
			ld ans = 0;
			for (int i = 0; i < M - 1; ++i) {
				po from(points[i]);
				po to(points[i + 1]);
				long long int dis = getdis(from, to);
				long long int amax = 1e18, bmax = 1e18;
				tree.get_closest(from, amax);
				tree.get_closest(to, bmax);
				ans += min(sqrt(dis), sqrt(amax) + sqrt(bmax));
			}
			cout << ans << endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 26384
final_rank: 12

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

#define dump(...) cout<<"# "<<#__VA_ARGS__<<'='<<(__VA_ARGS__)<<endl
#define repi(i,a,b) for(int i=int(a);i<int(b);i++)
#define peri(i,a,b) for(int i=int(b);i-->int(a);)
#define rep(i,n) repi(i,0,n)
#define per(i,n) peri(i,0,n)
#define all(c) begin(c),end(c)
#define mp make_pair
#define mt make_tuple

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;

template<typename T1,typename T2>
ostream& operator<<(ostream& os,const pair<T1,T2>& p){
	return os<<'('<<p.first<<','<<p.second<<')';
}

template<typename Tuple>
void print_tuple(ostream&,const Tuple&){}
template<typename Car,typename... Cdr,typename Tuple>
void print_tuple(ostream& os,const Tuple& t){
	print_tuple<Cdr...>(os,t);
	os<<(sizeof...(Cdr)?",":"")<<get<sizeof...(Cdr)>(t);
}
template<typename... Args>
ostream& operator<<(ostream& os,const tuple<Args...>& t){
	print_tuple<Args...>(os<<'(',t);
	return os<<')';
}

template<typename Ch,typename Tr,typename C>
basic_ostream<Ch,Tr>& operator<<(basic_ostream<Ch,Tr>& os,const C& c){
	os<<'[';
	for(auto i=begin(c);i!=end(c);++i)
		os<<(i==begin(c)?"":" ")<<*i;
	return os<<']';
}

constexpr int INF=1e9;
constexpr int MOD=1e9+7;
constexpr double EPS=1e-9;

struct Point{
	int x,y,z;
	Point():x(0),y(0),z(0){}
	Point(int x,int y,int z):x(x),y(y),z(z){}
};
ostream& operator<<(ostream& os,const Point& p){
	return os<<'('<<p.x<<','<<p.y<<','<<p.z<<')';
}
double Distance(Point a,Point b){
	double x=a.x-b.x,y=a.y-b.y,z=a.z-b.z;
	return sqrt(x*x+y*y+z*z);
}

template<typename T> void chmin(T& a,const T& b){a=min(a,b);}
template<typename T> void chmax(T& a,const T& b){a=max(a,b);}

int main()
{
	#ifndef _GLIBCXX_DEBUG
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	constexpr char endl='\n';
	#endif
	
	for(int n,q;cin>>n>>q && n|q;){
		vector<Point> warps(n); // warp
		for(auto& p:warps) cin>>p.x>>p.y>>p.z;
		vector<vector<Point>> paths(q); // path
		rep(i,q){
			int m; cin>>m;
			paths[i].resize(m);
			for(auto& p:paths[i]) cin>>p.x>>p.y>>p.z;
		}
		
		Point offset(INF,INF,INF);
		for(auto p:warps)
			chmin(offset.x,p.x),chmin(offset.y,p.y),chmin(offset.z,p.z);
		rep(i,q) for(auto p:paths[i])
			chmin(offset.x,p.x),chmin(offset.y,p.y),chmin(offset.z,p.z);
		for(auto& p:warps)
			p.x-=offset.x,p.y-=offset.x,p.z-=offset.z;
		rep(i,q) for(auto& p:paths[i])
			p.x-=offset.x,p.y-=offset.x,p.z-=offset.z;
		
		const int c=cbrt(n/10.+1); // 分割数．1区画あたり10個くらいの点があるように分割する．
		Point size(0,0,0); // 1区画あたりの大きさ
		for(auto p:warps)
			chmax(size.x,p.x),chmax(size.y,p.y),chmax(size.z,p.z);
		rep(i,q) for(auto p:paths[i])
			chmax(size.x,p.x),chmax(size.y,p.y),chmax(size.z,p.z);
		size.x=(size.x+c)/c,size.y=(size.y+c)/c,size.z=(size.z+c)/c;
		
		typedef vector<Point> vp;
		typedef vector<vp> vvp;
		typedef vector<vvp> vvvp;
		typedef vector<vvvp> vvvvp;
		vvvvp grid(c,vvvp(c,vvp(c)));
		for(auto p:warps)
			grid[p.x/size.x][p.y/size.y][p.z/size.z].push_back(p);
		
		for(auto path:paths){
			vd nears;
			for(auto p:path){
				double mn=INF;
				int ix=p.x/size.x,iy=p.y/size.y,iz=p.z/size.z;
				repi(i,max(ix-1,0),min(ix+2,c))
				repi(j,max(iy-1,0),min(iy+2,c))
				repi(k,max(iz-1,0),min(iz+2,c))
				for(auto q:grid[i][j][k])
					mn=min(mn,Distance(p,q));
				nears.push_back(mn);
			}
			double sum=0;
			rep(i,path.size()-1)
				sum+=min(Distance(path[i],path[i+1]),nears[i]+nears[i+1]);
			printf("%.9f\n",sum);
		}
	}
}
accuracy: 1
time_ms: 500
memory_kb: 5896
final_rank: 2

code_snippet: #include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
pair<long long,pair<long long,long long> > p[110000];
long long x[110000];
long long y[110000];
long long z[110000];
double d[110];
long long tx[110];
long long ty[110];
long long tz[110];
int main(){
	int a,b;
	while(scanf("%d%d",&a,&b),a){
		for(int i=0;i<a;i++){
			scanf("%lld%lld%lld",x+i,y+i,z+i);
			p[i]=make_pair(x[i],make_pair(y[i],z[i]));
		}
		std::sort(p,p+a);
		for(int i=0;i<a;i++){
			x[i]=p[i].first;
			y[i]=p[i].second.first;
			z[i]=p[i].second.second;
		}
		while(b--){
			int c;scanf("%d",&c);
			for(int i=0;i<c;i++){
				long long X,Y,Z;
				scanf("%lld%lld%lld",&X,&Y,&Z);
				tx[i]=X;ty[i]=Y;tz[i]=Z;
				int ind=lower_bound(x,x+a,X)-x;
				double tmp=999999999;
				for(int j=ind;j<a;j++){
					if((double)(x[j]-X)>tmp)break;
					tmp=min(tmp,sqrt((x[j]-X)*(x[j]-X)+(y[j]-Y)*(y[j]-Y)+(z[j]-Z)*(z[j]-Z)));
				}
				for(int j=ind-1;j>=0;j--){
					if((double)(X-x[j])>tmp)break;
					tmp=min(tmp,sqrt((x[j]-X)*(x[j]-X)+(y[j]-Y)*(y[j]-Y)+(z[j]-Z)*(z[j]-Z)));
				}
				d[i]=tmp;
	//			printf("%f ",d[i]);
			}
			double ret=0;
			for(int i=0;i<c-1;i++){
				ret+=min(sqrt((tx[i+1]-tx[i])*(tx[i+1]-tx[i])+(ty[i+1]-ty[i])*(ty[i+1]-ty[i])+(tz[i+1]-tz[i])*(tz[i+1]-tz[i])),d[i]+d[i+1]);
			}
			printf("%.12f\n",ret);
		}
	}
}
accuracy: 1
time_ms: 1850
memory_kb: 6084
final_rank: 10

code_snippet: #include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#define INF 1000001LL
#define INF2 100000001000000LL
using namespace std;

typedef long long ll;
typedef vector<ll> cord;

inline ll dis(cord &a, cord &b){
  if(a.size() != b.size())return INF2;
  ll res = 0;
  for(int i=0;i<a.size();i++)res += (a[i]-b[i]) * (a[i]-b[i]);
  return res;
}

struct KDTree{
  int n,d;
  vector<cord> v;

  void heap_sort(int l,int r,int &k){
    if(r-l<=1)return;
    int now,nxt;
    for(int i=1;i<r-l;i++){
      now = i;
      while(now){
	nxt = (now-1)>>1;
	if(v[l+nxt][k] < v[l+now][k])swap(v[l+nxt],v[l+now]);
	else break;
	now = nxt;
      }
    }

    for(int i=r-l-1;i>0;i--){
      swap(v[l+i],v[l]);
      now = 0; nxt = (now+1)<<1;
      while(nxt-1 < i){
	if(v[l+now][k] < v[l+nxt-1][k]){
	  if(nxt<i && v[l+nxt-1][k] < v[l+nxt][k]){
	    swap(v[l+now],v[l+nxt]);
	    now = nxt;
	  }else{
	    swap(v[l+now],v[l+nxt-1]);
	    now = nxt-1;
	  }
	}else if(nxt<i && v[l+now][k] < v[l+nxt][k]){
	  swap(v[l+now],v[l+nxt]);
	  now = nxt;
	}else break;
	nxt = (now+1)<<1;
      }
    }
  }

  void compose(int l, int r, int depth){
    if(r-l<1)return;
    heap_sort(l,r,depth);

    compose(l,(l+r)/2,(depth+1)%d);
    compose((l+r)/2+1,r,(depth+1)%d);
  }

  void search(int l,int r,vector<ll>& b, cord& p, int depth, ll& dist){
    if(r-l<1)return;

    int mid = (l+r)/2;
    ll tmp;
    dist = min(dist,dis(p,v[mid]));

    for(int i=0;i<d;i++){
      tmp = b[2*i]-p[i];
      if(tmp>0 && tmp*tmp >= dist)return;
      tmp = b[2*i+1]-p[i];
      if(tmp<0 && tmp*tmp >= dist)return;
    }

    for(int i=0;i<3;i++){
      if(p[depth]>v[mid][depth] && i==2)continue;
      if(p[depth]<=v[mid][depth] && i==0)continue;
      int f = i&1;
      tmp = b[2*depth+f];
      b[2*depth+f] = v[mid][depth]; 
      if(f)search(l,mid,b,p,(depth+1)%d,dist);
      else search(mid+1,r,b,p,(depth+1)%d,dist);
      b[2*depth+f] = tmp;
    }
  }
};

int n,q,m;
cord p(3),r(3);
KDTree kd;

int main(){
  vector<ll> box;
  for(int i=0;i<3;i++){
    box.push_back(-INF); 
    box.push_back(INF);
  }

  while(scanf("%d%d",&n,&q)!=EOF,n||q){
    kd.v.resize(n);
    kd.n = n; kd.d = 3;

    for(int i=0;i<n;i++){
      kd.v[i].resize(3);
      for(int j=0;j<3;j++)scanf("%lld",&kd.v[i][j]);
    }

    kd.compose(0,n,0);

    for(int i=0;i<q;i++){
      scanf("%d",&m);
      double ans = 0;
      ll now,prv;

      for(int j=0;j<3;j++)scanf("%lld",&p[j]);
      prv = INF2;
      kd.search(0,n,box,p,0,prv);

      for(int j=1;j<m;j++){
	for(int k=0;k<3;k++)scanf("%lld",&r[k]);
	now = INF2;
	kd.search(0,n,box,r,0,now);

	ans += min( sqrt(prv) + sqrt(now), sqrt(dis(p,r)) );
	prv = now; p = r;
      }
      printf("%.9lf\n",ans);
    }
  }
}
accuracy: 1
time_ms: 480
memory_kb: 6436
final_rank: 3

code_snippet: #include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#include<iostream>
#define INF 1000001LL
#define INF2 100000001000000LL
using namespace std;

typedef long long ll;
typedef vector<ll> cord;

#define N 100000

ll dis(cord &a, cord &b){
  if(a.size() != b.size())return INF;
  ll res = 0;
  for(int i=0;i<a.size();i++)res += (a[i]-b[i]) * (a[i]-b[i]);
  return res;
}

struct KDTree{
  int n,d;
  vector<cord> v;

  void heap(int l,int r,int &k){
    if(r-l<=1)return;
    int now,nxt;
    for(int i=1;i<r-l;i++){
      now = i;
      while(now){
	nxt = (now-1)>>1;
	if(v[l+nxt][k] < v[l+now][k])swap(v[l+nxt],v[l+now]);
	else break;
	now = nxt;
      }
    }

    for(int i=r-l-1;i>0;i--){
      swap(v[l+i],v[l]);
      now = 0; nxt = (now+1)<<1;
      while(nxt-1 < i){
	if(v[l+now][k] < v[l+nxt-1][k]){
	  if(nxt<i && v[l+nxt-1][k] < v[l+nxt][k]){
	    swap(v[l+now],v[l+nxt]);
	    now = nxt;
	  }else{
	    swap(v[l+now],v[l+nxt-1]);
	    now = nxt-1;
	  }
	}else if(nxt<i && v[l+now][k] < v[l+nxt][k]){
	  swap(v[l+now],v[l+nxt]);
	  now = nxt;
	}else break;
	nxt = (now+1)<<1;
      }
    }
  }

  void compose(int l, int r, int depth){
    if(r-l<1)return;
    heap(l,r,depth);

    compose(l,(l+r)/2,(depth+1)%d);
    compose((l+r)/2+1,r,(depth+1)%d);
  }

  void search(int l,int r,vector<ll>& b, cord& p, int depth, ll& dist){
    if(r-l<1)return;

    int mid = (l+r)/2;
    ll tmp;
    dist = min(dist,dis(p,v[mid]));

    for(int i=0;i<d;i++){
      tmp = b[2*i]-p[i];
      if(tmp>0 && tmp*tmp >= dist)return;
      tmp = b[2*i+1]-p[i];
      if(tmp<0 && tmp*tmp >= dist)return;
    }

    for(int i=0;i<3;i++){
      if(p[depth]>v[mid][depth] && i==2)continue;
      if(p[depth]<=v[mid][depth] && i==0)continue;
      int f = i&1;
      tmp = b[2*depth+f];
      b[2*depth+f] = v[mid][depth]; 
      if(f)search(l,mid,b,p,(depth+1)%d,dist);
      else search(mid+1,r,b,p,(depth+1)%d,dist);
      b[2*depth+f] = tmp;
    }
  }
};

int n,q,m;
cord p(3),r(3);
KDTree kd;

int main(){
  vector<ll> box;
  for(int i=0;i<3;i++){
    box.push_back(-INF); 
    box.push_back(INF);
  }

  while(scanf("%d%d",&n,&q)!=EOF,n||q){
    kd.v.resize(n);
    kd.n = n; kd.d = 3;

    for(int i=0;i<n;i++){
      kd.v[i].resize(3);
      for(int j=0;j<3;j++)scanf("%lld",&kd.v[i][j]);
    }

    kd.compose(0,n,0);

    for(int i=0;i<q;i++){
      scanf("%d",&m);
      double ans = 0;
      ll now,prv;

      for(int j=0;j<3;j++)scanf("%lld",&p[j]);
      prv = INF2;
      kd.search(0,n,box,p,0,prv);

      for(int j=1;j<m;j++){
	for(int k=0;k<3;k++)scanf("%lld",&r[k]);
	now = INF2;
	kd.search(0,n,box,r,0,now);

	ans += min( sqrt(prv) + sqrt(now), sqrt(dis(p,r)) );
	prv = now; p = r;
      }
      printf("%.9lf\n",ans);
    }
  }
}
accuracy: 1
time_ms: 490
memory_kb: 6572
final_rank: 4

code_snippet: #include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#define INF 1000001LL
#define INF2 100000001000000LL
using namespace std;

typedef long long ll;
typedef vector<ll> cord;

#define N 100000

ll dis(cord &a, cord &b){
  if(a.size() != b.size())return INF;
  ll res = 0;
  for(int i=0;i<a.size();i++)res += (a[i]-b[i]) * (a[i]-b[i]);
  return res;
}

struct KDTree{
  int n,d;
  vector<cord> v,tmp;

  void merge(int l,int r,int &k){
    if(r-l<=1)return;
    int mid = (l+r)/2;
    
    merge(l,mid,k); merge(mid,r,k);
    int x=l,y=mid,pos=l;

    while(x<mid && y<r){
    if(v[x][k]>v[y][k])tmp[pos++] = v[y++];
    else tmp[pos++] = v[x++];
    }
    while(x<mid)tmp[pos++] = v[x++];
    while(y<r)tmp[pos++] = v[y++];
    
    for(int i=l;i<r;i++)v[i] = tmp[i];
  }

  void compose(int l, int r, int depth){
    if(r-l<1)return;
    merge(l,r,depth);

    compose(l,(l+r)/2,(depth+1)%d);
    compose((l+r)/2+1,r,(depth+1)%d);
  }

  void search(int l,int r,vector<ll>& b, cord& p, int depth, ll& dist){
    if(r-l<1)return;

    int mid = (l+r)/2;
    ll tmp;
    dist = min(dist,dis(p,v[mid]));

    for(int i=0;i<d;i++){
      tmp = b[2*i]-p[i];
      if(tmp>0 && tmp*tmp >= dist)return;
      tmp = b[2*i+1]-p[i];
      if(tmp<0 && tmp*tmp >= dist)return;
    }

    for(int i=0;i<3;i++){
      if(p[depth]>v[mid][depth] && i==2)continue;
      if(p[depth]<=v[mid][depth] && i==0)continue;
      int f = i&1;
      tmp = b[2*depth+f];
      b[2*depth+f] = v[mid][depth]; 
      if(f)search(l,mid,b,p,(depth+1)%d,dist);
      else search(mid+1,r,b,p,(depth+1)%d,dist);
      b[2*depth+f] = tmp;
    }
  }
};

int n,q,m;
cord p(3),r(3);
KDTree kd;

int main(){
  vector<ll> box;
  for(int i=0;i<3;i++){
    box.push_back(-INF); 
    box.push_back(INF);
  }

  while(scanf("%d%d",&n,&q)!=EOF,n||q){
    kd.v.resize(n); kd.tmp.resize(n);
    kd.n = n; kd.d = 3;

    for(int i=0;i<n;i++){
      kd.v[i].resize(3);
      for(int j=0;j<3;j++)scanf("%lld",&kd.v[i][j]);
    }

    kd.compose(0,n,0);

    for(int i=0;i<q;i++){
      scanf("%d",&m);
      double ans = 0;
      ll now,prv;

      for(int j=0;j<3;j++)scanf("%lld",&p[j]);
      prv = INF2;
      kd.search(0,n,box,p,0,prv);

      for(int j=1;j<m;j++){
	for(int k=0;k<3;k++)scanf("%lld",&r[k]);
	now = INF2;
	kd.search(0,n,box,r,0,now);

	ans += min( sqrt(prv) + sqrt(now), sqrt(dis(p,r)) );
	prv = now; p = r;
      }
      printf("%.9lf\n",ans);
    }
  }
}
accuracy: 1
time_ms: 620
memory_kb: 11936
final_rank: 6

code_snippet: #include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#define INF 1000001LL
#define INF2 100000001000000LL
using namespace std;

typedef long long ll;

#define N 100000

struct cord{
  int d;
  vector<ll> c;
  cord(void){d = 0;c.clear();}
  cord(vector<ll> v){d = v.size(); c = v;}

  ll dis(cord &a){
    if(a.d != d)return INF;
    ll res = 0;
    for(int i=0;i<d;i++)res += (a.c[i]-c[i]) * (a.c[i]-c[i]);
    return res;
  }
};

struct KDTree{
  int n,d;
  vector<cord> v,tmp;

  KDTree(void){n = d = 0;v.clear();}
  KDTree(vector<cord> x){
    n = x.size();
    if(!n)return;
    d = x[0].c.size();
    if(!d)return;
    v = x;
    tmp.resize(n);
    compose(0,n,0);
  }

  void merge(int l,int r,int k){
    if(r-l<=1)return;
    int mid = (l+r)/2;
    
    merge(l,mid,k); merge(mid,r,k);
    int x=l,y=mid,pos=l;

    while(x<mid && y<r){
    if(v[x].c[k]>v[y].c[k])tmp[pos++] = v[y++];
    else tmp[pos++] = v[x++];
    }
    while(x<mid)tmp[pos++] = v[x++];
    while(y<r)tmp[pos++] = v[y++];
    
    for(int i=l;i<r;i++)v[i] = tmp[i];
  }

  void compose(int l, int r, int depth){
    if(r-l<1)return;
    merge(l,r,depth);

    compose(l,(l+r)/2,(depth+1)%d);
    compose((l+r)/2+1,r,(depth+1)%d);
  }

  void search(int l,int r,vector<ll>& b, cord& p, int depth, ll& dist){
    if(r-l<1)return;

    int mid = (l+r)/2;
    ll tmp;
    dist = min(dist,p.dis(v[mid]));

    for(int i=0;i<d;i++){
      tmp = b[2*i]-p.c[i];
      if(tmp>0 && tmp*tmp >= dist)return;
      tmp = b[2*i+1]-p.c[i];
      if(tmp<0 && tmp*tmp >= dist)return;
    }

    for(int i=0;i<3;i++){
      if(p.c[depth]>v[mid].c[depth] && i==2)continue;
      if(p.c[depth]<=v[mid].c[depth] && i==0)continue;
      int f = i&1;
      tmp = b[2*depth+f];
      b[2*depth+f] = v[mid].c[depth]; 
      if(f)search(l,mid,b,p,(depth+1)%d,dist);
      else search(mid+1,r,b,p,(depth+1)%d,dist);
      b[2*depth+f] = tmp;
    }
  }
};

int n,q,m;
vector<cord> v;
cord p,r;
vector<ll> tmp;   

int main(){
  vector<ll> box;
  for(int i=0;i<3;i++){
    box.push_back(-INF); 
    box.push_back(INF);
  }

  while(scanf("%d%d",&n,&q)!=EOF,n||q){
    v.resize(n); tmp.resize(3);

    for(int i=0;i<n;i++){
      for(int j=0;j<3;j++)scanf("%lld",&tmp[j]);
      v[i] = cord(tmp);
    }

    KDTree kd(v);

    for(int i=0;i<q;i++){
      scanf("%d",&m);
      double ans = 0;
      ll now,prv;

      for(int j=0;j<3;j++)scanf("%lld",&tmp[j]);
      p = cord(tmp); prv = INF2;
      kd.search(0,n,box,p,0,prv);

      for(int j=1;j<m;j++){
	for(int k=0;k<3;k++)scanf("%lld",&tmp[k]);
	r = cord(tmp); now = INF2;
	kd.search(0,n,box,r,0,now);

	ans += min(sqrt(prv) + sqrt(now), sqrt(p.dis(r)) );
	prv = now; p = r;
      }
      printf("%.9lf\n",ans);
    }
  }
}
accuracy: 1
time_ms: 690
memory_kb: 25824
final_rank: 15

code_snippet: #include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#define INF 1000001LL
#define INF2 100000001000000LL
using namespace std;

typedef long long ll;

struct cord{
  int d,k;
  vector<ll> c;
  cord(void){d = k = 0;c.clear();}
  cord(vector<ll> v){d = v.size(); k = 0; c = v;}
  bool operator<(const cord a)const{return c[k]<a.c[k];}

  ll dis(cord &a){
    if(a.d != d)return INF;
    ll res = 0;
    for(int i=0;i<d;i++)res += (a.c[i]-c[i]) * (a.c[i]-c[i]);
    return res;
  }
};

struct KDTree{
  int n,d;
  vector<cord> v;

  KDTree(void){n = d = 0;v.clear();}
  KDTree(vector<cord> x){
    n = x.size();
    if(!n)return;
    d = x[0].c.size();
    if(!d)return;
    v = x;
    compose(0,n,0);
  }

  void compose(int l, int r, int depth){
    if(r-l<1)return;
    for(int i=l;i<r;i++)v[i].k = depth;
    sort(v.begin()+l,v.begin()+r);

    compose(l,(l+r)/2,(depth+1)%d);
    compose((l+r)/2+1,r,(depth+1)%d);
  }

  void search(int l,int r,vector<ll>& b, cord& p, int depth, ll& dist){
    if(r-l<1)return;

    int mid = (l+r)/2;
    ll tmp;
    dist = min(dist,p.dis(v[mid]));

    for(int i=0;i<d;i++){
      tmp = b[2*i]-p.c[i];
      if(tmp>0 && tmp*tmp >= dist)return;
      tmp = b[2*i+1]-p.c[i];
      if(tmp<0 && tmp*tmp >= dist)return;
    }

    for(int i=0;i<3;i++){
      if(p.c[depth]>v[mid].c[depth] && i==2)continue;
      if(p.c[depth]<=v[mid].c[depth] && i==0)continue;
      int f = i&1;
      tmp = b[2*depth+f];
      b[2*depth+f] = v[mid].c[depth]; 
      if(f)search(l,mid,b,p,(depth+1)%d,dist);
      else search(mid+1,r,b,p,(depth+1)%d,dist);
      b[2*depth+f] = tmp;
    }
  }
};

int n,q,m;
vector<cord> v;
cord p,r;
vector<ll> tmp;   

int main(){
  vector<ll> box;
  for(int i=0;i<3;i++){
    box.push_back(-INF); 
    box.push_back(INF);
  }

  while(scanf("%d%d",&n,&q)!=EOF,n||q){
    v.resize(n); tmp.resize(3);

    for(int i=0;i<n;i++){
      for(int j=0;j<3;j++)scanf("%lld",&tmp[j]);
      v[i] = cord(tmp);
    }

    KDTree kd(v);

    for(int i=0;i<q;i++){
      scanf("%d",&m);
      double ans = 0;
      ll now, prv;

      for(int j=0;j<3;j++)scanf("%lld",&tmp[j]);
      p = cord(tmp); prv = INF2;
      kd.search(0,n,box,p,0,prv);

      for(int j=1;j<m;j++){
	for(int k=0;k<3;k++)scanf("%lld",&tmp[k]);
	r = cord(tmp); now = INF2;
	kd.search(0,n,box,r,0,now);

	ans += min(sqrt(prv) + sqrt(now), sqrt(p.dis(r)) );
	prv = now; p = r;
      }
      printf("%.9lf\n",ans);
    }
  }
}
accuracy: 1
time_ms: 1110
memory_kb: 19556
final_rank: 14

code_snippet: #include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#define INF 1000001LL
#define INF2 100000001000000LL
using namespace std;

typedef long long ll;

struct cord{
  int d,k;
  vector<ll> c;
  cord(void){d = k = 0;c.clear();}
  cord(vector<ll> v){d = v.size(); k = 0; c = v;}
  bool operator<(const cord a)const{return c[k]<a.c[k];}

  ll dis(cord &a){
    if(a.d != d)return INF;
    ll res = 0;
    for(int i=0;i<d;i++)res += (a.c[i]-c[i]) * (a.c[i]-c[i]);
    return res;
  }
};

struct KDTree{
  int n,d;
  vector<cord> v;

  KDTree(void){n = d = 0;v.clear();}
  KDTree(vector<cord> x){
    n = x.size();
    if(!n)return;
    d = x[0].c.size();
    if(!d)return;
    v = x;
    compose(0,n,0);
  }

  void compose(int l, int r, int depth){
    if(r-l<1)return;
    for(int i=l;i<r;i++)v[i].k = depth;
    sort(v.begin()+l,v.begin()+r);

    compose(l,(l+r)/2,(depth+1)%d);
    compose((l+r)/2+1,r,(depth+1)%d);
  }

  void search(int l,int r,vector<ll>& b, cord& p, int depth, ll& dist){
    if(r-l<1)return;

    int mid = (l+r)/2;
    dist = min(dist,p.dis(v[mid]));
    for(int i=0;i<d;i++){
      if(b[2*i]>p.c[i] && (b[2*i]-p.c[i])*(b[2*i]-p.c[i]) >= dist)return;
      else if(b[2*i+1]<p.c[i] && (b[2*i+1]-p.c[i])*(b[2*i+1]-p.c[i]) >= dist)return;
    }

    ll tmp;
    if(p.c[depth]>v[mid].c[depth]){
      tmp = b[2*depth];
      b[2*depth] = v[mid].c[depth]; 
      search(mid+1,r,b,p,(depth+1)%d,dist);
      b[2*depth] = tmp;
    }

    tmp = b[2*depth+1];
    b[2*depth+1] = v[mid].c[depth]; 
    search(l,mid,b,p,(depth+1)%d,dist);
    b[2*depth+1] = tmp;

    if(p.c[depth]<=v[mid].c[depth]){
      tmp = b[2*depth];
      b[2*depth] = v[mid].c[depth]; 
      search(mid+1,r,b,p,(depth+1)%d,dist);
      b[2*depth] = tmp;
    }
  }
};

int n,q,m;
vector<cord> v;
cord p,r;
vector<ll> tmp;   

int main(){
  vector<ll> box;
  for(int i=0;i<3;i++){
    box.push_back(-INF); 
    box.push_back(INF);
  }

  while(scanf("%d%d",&n,&q)!=EOF,n||q){
    v.resize(n); tmp.resize(3);

    for(int i=0;i<n;i++){
      for(int j=0;j<3;j++)scanf("%lld",&tmp[j]);
      v[i] = cord(tmp);
    }

    KDTree kd(v);

    for(int i=0;i<q;i++){
      scanf("%d",&m);
      double ans = 0;
      ll now, prv;

      for(int j=0;j<3;j++)scanf("%lld",&tmp[j]);
      p = cord(tmp); prv = INF2;
      kd.search(0,n,box,p,0,prv);

      for(int j=1;j<m;j++){
	for(int k=0;k<3;k++)scanf("%lld",&tmp[k]);
	r = cord(tmp); now = INF2;
	kd.search(0,n,box,r,0,now);

	ans += min(sqrt(prv) + sqrt(now), sqrt(p.dis(r)) );
	prv = now; p = r;
      }
      printf("%.9lf\n",ans);
    }
  }
}
accuracy: 1
time_ms: 1070
memory_kb: 19556
final_rank: 13

code_snippet: #include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#include<iostream>
#include<cmath>
#define INF 1000001LL
#define INF2 100000001000000LL
using namespace std;

typedef long long ll;

struct cord{
  int d,k;
  vector<ll> c;
  cord(void){d = k = 0;c.clear();}
  cord(vector<ll> v){d = v.size(); k = 0; c = v;}
  bool operator<(const cord a)const{return c[k]<a.c[k];}
  bool operator==(const cord a)const{return c==a.c;}
};

ll dis(cord a, cord b){
  if(a.d != b.d)return INF;
  ll res = 0;
  for(int i=0;i<a.d;i++)res += (a.c[i]-b.c[i]) * (a.c[i]-b.c[i]);
  return res;
}

struct KDTree{
  int n,d,root;
  vector<cord> v;

  KDTree(void){n = d = root = 0;v.clear();}

  KDTree(vector<cord> x){
    n = x.size();
    if(!n)return;
    d = x[0].c.size();
    if(!d)return;
    v = x;
    compose(0,n,0);
  }

  void compose(int l, int r, int depth){
    if(r-l<=1)return;
    for(int i=l;i<r;i++)v[i].k = depth;
    sort(v.begin()+l,v.begin()+r);

    compose(l,(l+r)/2,(depth+1)%d);
    compose((l+r)/2+1,r,(depth+1)%d);
  }

  inline void search(int l,int r,vector<ll> &rng, cord p, int depth, ll &dist){
    if(r-l<1)return;

    int mid = (l+r)/2;
    dist = min(dist,dis(p,v[mid]));
    for(int i=0;i<d;i++){
      if(rng[2*i]>p.c[i] && (rng[2*i]-p.c[i])*(rng[2*i]-p.c[i]) >= dist)return;
      else if(rng[2*i+1]<p.c[i] && (rng[2*i+1]-p.c[i])*(rng[2*i+1]-p.c[i]) >= dist)return;
    }

    ll tmp,nxt[4],st[] = {0,1},d1,d2;
    nxt[0] = mid+1; nxt[1] = r; nxt[2] = l; nxt[3] = mid;

    if(p.c[depth]<v[mid].c[depth]){
      swap(nxt[0],nxt[2]);
      swap(nxt[1],nxt[3]);
      swap(st[0],st[1]);
    }
    
    for(int i=0;i<2;i++){
      tmp = rng[2*depth+st[i]];
      rng[2*depth+st[i]] = v[mid].c[depth]; 
      search(nxt[2*i],nxt[2*i+1],rng,p,(depth+1)%d,dist);
      rng[2*depth+st[i]] = tmp;
    }
  }
};

int n,q,m;
vector<cord> v;
cord p,r;
vector<ll> tmp;   

int main(){
  vector<ll> range;
  for(int i=0;i<3;i++){
    range.push_back(-INF); 
    range.push_back(INF);
  }

  while(scanf("%d%d",&n,&q)!=EOF,n||q){
    v.resize(n); tmp.resize(3);

    for(int i=0;i<n;i++){
      for(int j=0;j<3;j++)scanf("%lld",&tmp[j]);
      v[i] = cord(tmp);
    }

    KDTree kd(v);

    for(int i=0;i<q;i++){
      scanf("%d",&m);
      double ans = 0;
      ll now, prv;

      for(int j=0;j<3;j++)scanf("%lld",&tmp[j]);
      p = cord(tmp); prv = INF2;
      kd.search(0,n,range,p,0,prv);
      for(int j=1;j<m;j++){
	for(int k=0;k<3;k++)scanf("%lld",&tmp[k]);

	r = cord(tmp); now = INF2;
	kd.search(0,n,range,r,0,now);
	ans += min(sqrt(prv) + sqrt(now), sqrt(dis(p,r)) );
	prv = now; p = r;
      }
      printf("%.9lf\n",ans);
    }
  }
}
accuracy: 1
time_ms: 1850
memory_kb: 19700
final_rank: 16

code_snippet: #include <iostream>
#include <cstdio>
#include <cmath>
#include <complex>
#include <algorithm>
using namespace std;
struct P{
	double x,y,z;
	P(double x,double y,double z) : x(x) , y(y) , z(z) {}
	P(){x=y=z=0;}
};

bool operator < (const P &a,const P &b){
	return a.x < b.x;
}

P p[100000];
P q[100];

double dist[100];
int n,Q;

void calc(int idx){
	dist[idx] = 1e15;
	/*for(int i = 0 ; i < n ; i++){
		double dx = (p[i].x-q[idx].x)*(p[i].x-q[idx].x);
		double dy = (p[i].y-q[idx].y)*(p[i].y-q[idx].y);
		double dz = (p[i].z-q[idx].z)*(p[i].z-q[idx].z);	
		dist[idx] = min( dist[idx] , sqrt(dx+dy+dz) );
	}*/
	int s = lower_bound(p,p+n,q[idx]) - p;
	for(int i = s ; i < n && abs(p[i].x-q[idx].x) < dist[idx] ; i++){
		double dx = (p[i].x-q[idx].x)*(p[i].x-q[idx].x);
		double dy = (p[i].y-q[idx].y)*(p[i].y-q[idx].y);
		double dz = (p[i].z-q[idx].z)*(p[i].z-q[idx].z);	
		dist[idx] = min( dist[idx] , sqrt(dx+dy+dz) );
	}
	for(int i = s-1 ; i >= 0 && abs(p[i].x-q[idx].x) < dist[idx] ; i--){
		double dx = (p[i].x-q[idx].x)*(p[i].x-q[idx].x);
		double dy = (p[i].y-q[idx].y)*(p[i].y-q[idx].y);
		double dz = (p[i].z-q[idx].z)*(p[i].z-q[idx].z);	
		dist[idx] = min( dist[idx] , sqrt(dx+dy+dz) );
	}
}

int main(){
	while(cin >> n >> Q&& n){
		for(int i = 0 ; i < n ; i++) scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
		sort(p,p+n);
		while(Q--){
			int m;
			cin >> m;
			for(int i = 0 ; i < m ; i++){
				scanf("%lf%lf%lf",&q[i].x,&q[i].y,&q[i].z);
				calc(i);
			}
			double res = 0;
			for(int i = 1 ; i < m ; i++){
				double dx = (q[i].x-q[i-1].x)*(q[i].x-q[i-1].x);
				double dy = (q[i].y-q[i-1].y)*(q[i].y-q[i-1].y);
				double dz = (q[i].z-q[i-1].z)*(q[i].z-q[i-1].z);
				
				res += min( dist[i] + dist[i-1] , sqrt(dx+dy+dz) );
			}
			printf("%.10lf\n",res);
		}
	}
}
accuracy: 1
time_ms: 1660
memory_kb: 3632
final_rank: 9

code_snippet: #include<iostream>
#include<climits>
#include<cassert>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cstdlib>
#include<functional>
#include<iomanip>
#include<cstdio>
#include<set>

using namespace std;

const double inf = 1e80;

struct point3d{

  long long x,y,z;

  point3d():x(0),y(0),z(0){}
  point3d(long long x, long long y, long long z):x(x),y(y),z(z){}

  inline bool compare(int d, const point3d &t) const {
    if( d == 0 ){
      return x < t.x;
    }else if( d == 1 ){
      return y < t.y;
    }else if( d == 2 ){
      return z < t.z;
    }
    return false;
  }

  inline bool operator<(const point3d &t) const {
    if(x!=t.x)return x<t.x;
    if(y!=t.y)return y<t.y;
    if(z!=t.z)return z<t.z;
    return false;
  }
  
  inline long long dist2(const point3d &t) const {
    long long ret = (x-t.x)*(x-t.x) + (y-t.y) * (y-t.y) + (z-t.z) * (z-t.z);
    return ret;
  }

  inline long long ddist2(int d, const point3d &t)const{
    if( d == 0 ){
      return (x-t.x) * (x-t.x);
    }else if( d == 1 ){
      return (y-t.y) * (y-t.y);
    }else if( d == 2 ){
      return (z-t.z) * (z-t.z);
    }return 0;
  }
  
};

inline bool comp_x(const point3d &a, const point3d &b){return a.x<b.x;}
inline bool comp_y(const point3d &a, const point3d &b){return a.y<b.y;}
inline bool comp_z(const point3d &a, const point3d &b){return a.z<b.z;}


long long call = 0;

struct kdtree{

  struct node{
    point3d p;
    node *l;
    node *r;
    node(const point3d &p) : p(p), l(NULL), r(NULL){}
  }*root;

  kdtree() : root(NULL) { }

  void insert(const point3d &p){
    root = insert( root, 0, p );
  }

  node *insert(node *t, int d, const point3d &p){
    ++call;
    if( t == NULL ) return new node(p);
    if( p.compare(d,t->p) )
      t->l = insert(t->l, (d+1)%3, p);
    else
      t->r = insert(t->r, (d+1)%3, p);
    return t;
  }

  node * build(int d, point3d ps[], int l, int r){
    if(l+1==r){
      return new node(ps[l]);
    }
    if(d==0){
      sort(ps+l,ps+r,comp_x);
    }else if(d==1){
      sort(ps+l,ps+r,comp_y);
    }else if(d==2){
      sort(ps+l,ps+r,comp_z);
    }
    int m = (l+r)/2;
    node * ret = new node(ps[m]);
    if(m>l)
      ret->l = build((d+1)%3,ps,l,m);
    if(r>m+1)
      ret->r = build((d+1)%3,ps,m+1,r);
    return ret;
  }

  long long best;
  node * best_near;
  point3d nearest(const point3d &p){
    best = 1LL<<55;
    best_near = NULL;
    nearest(root,0,p);
    return best_near->p;
  }
  
  void nearest(node *cur, int d, const point3d &p){
    ++call;
    bool bc = p.compare(d,cur->p);
    node * next      = bc ? cur->l : cur->r;
    node * next_anoc = bc ? cur->r : cur->l;

    // refresh
    if( best > p.dist2(cur->p) ){
      best = p.dist2(cur->p);
      best_near = cur;
    }

    // down
    if( next ){
      nearest(next,(d+1)%3, p);
    }

    // refresh
    if( best > p.dist2(cur->p) ){
      best = p.dist2(cur->p);
      best_near = cur;
    }
    
    if( best >= p.ddist2(d,cur->p) ){
      // down another
      if( next_anoc ){
        nearest(next_anoc, (d+1)%3, p);
      }
    }
    
    // up
    return ;
  }

  void calc_depth(node *t, int cur_depth, int &depth){
    depth=max(depth,cur_depth);
    if(t==NULL)return ;
    calc_depth(t->l,cur_depth+1,depth);
    calc_depth(t->r,cur_depth+1,depth);
  }

};

namespace std{
  ostream &operator<<(ostream &o, const point3d &t){
    o << '(' << t.x << ',' << t.y << ',' << t.z <<')';
    return o;
  }
}

int main()
{
  int n,q;
  // while( scanf("%d%d", &n, &q) != EOF ){
  while(cin >> n >> q){
    if( n == 0 && q == 0 ) break;
    kdtree kd;
    point3d *ary = new point3d[n];
    
    for(int i = 0; i < n; ++i){
      cin >> ary[i].x >> ary[i].y >> ary[i].z;
    }
    kd.root = kd.build(0,ary,0,n);

    // m q n^(2/3)

    // int depth = 0;
    // kd.calc_depth(kd.root,0,depth);
    // cout <<"Depth : " << depth << endl;

    call = 0;
    int m;
    for(int qq = 0; qq < q; ++qq){
      double res = 0;
      vector<point3d> route;

      // scanf("%d", &m);
      cin >> m;

      for(int i = 0; i < m; ++i){
        int x,y,z;
        // scanf("%d %d %d", &x, &y, &z);
        cin >> x >> y >> z;
        route.push_back(point3d(x,y,z));
      }


      for(int i = 0; i < (int)route.size()-1; ++i){
        point3d cur = route[i];
        point3d next = route[1+i];
        
        // call = 0;
        point3d nw1 = kd.nearest( cur );
        point3d nw2 = kd.nearest( next );

        // cout << call << ' ' << 2*3*pow(n,0.66666) << endl;
        
        double d0 = sqrt( cur.dist2(next) );
        double d1 = sqrt( cur.dist2(nw1) );
        double d2 = sqrt( next.dist2(nw2) );
        double d = min( d0, d1 + d2 );
        res += d;
        
      }
      
      printf("%.9lf\n", res);
    }
    
    // 11006221817
    // 1.29e09 = 1290000000

    // cout << "Total Call 2 : " << call << ' ' << m*q*2*(long long)3*pow(n,0.66666) << endl;
    // cout << "(ratio): " << (call / (double)(2*m*q*lgn) * 100) << " %" << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 400
memory_kb: 8280
final_rank: 5