Problem:
Score : 400 points

Problem Statement

Along a road running in an east-west direction, there are A shrines and B temples.
The i-th shrine from the west is located at a distance of s_i meters from the west end of the road, and the i-th temple from the west is located at a distance of t_i meters from the west end of the road.

Answer the following Q queries:

Query i (1 \leq i \leq Q): If we start from a point at a distance of x_i meters from the west end of the road and freely travel along the road, what is the minimum distance that needs to be traveled in order to visit one shrine and one temple? (It is allowed to pass by more shrines and temples than required.)

Constraints

1 \leq A, B \leq 10^5

1 \leq Q \leq 10^5

1 \leq s_1 < s_2 < ... < s_A \leq 10^{10}

1 \leq t_1 < t_2 < ... < t_B \leq 10^{10}

1 \leq x_i \leq 10^{10}

s_1, ..., s_A, t_1, ..., t_B, x_1, ..., x_Q are all different.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

A B Q
s_1
:
s_A
t_1
:
t_B
x_1
:
x_Q

Output

Print Q lines. The i-th line should contain the answer to the i-th query.

Sample Input 1

2 3 4
100
600
400
900
1000
150
2000
899
799

Sample Output 1

350
1400
301
399

There are two shrines and three temples. The shrines are located at distances of 100, 600 meters from the west end of the road, and the temples are located at distances of 400, 900, 1000 meters from the west end of the road.

Query 1: If we start from a point at a distance of 150 meters from the west end of the road, the optimal move is first to walk 50 meters west to visit a shrine, then to walk 300 meters east to visit a temple.

Query 2: If we start from a point at a distance of 2000 meters from the west end of the road, the optimal move is first to walk 1000 meters west to visit a temple, then to walk 400 meters west to visit a shrine. We will pass by another temple on the way, but it is fine.

Query 3: If we start from a point at a distance of 899 meters from the west end of the road, the optimal move is first to walk 1 meter east to visit a temple, then to walk 300 meters west to visit a shrine.

Query 4: If we start from a point at a distance of 799 meters from the west end of the road, the optimal move is first to walk 199 meters west to visit a shrine, then to walk 200 meters west to visit a temple.

Sample Input 2

1 1 3
1
10000000000
2
9999999999
5000000000

Sample Output 2

10000000000
10000000000
14999999998

The road is quite long, and we may need to travel a distance that does not fit into a 32-bit integer.

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace ABC119D
{
    class Program
    {
        public static void Solve(Input input)
        {
            var A = input.NextInt();
            var B = input.NextInt();
            var Q = input.NextInt();
            var s = input.NextLong(A);
            var t = input.NextLong(B);

            for (int i = 0; i < Q; i++)
            {
                var q = input.NextLong();
                var anslist = new List<long>();

                var nextj = Search.LowerBound(s, q);
                if (nextj < s.Length)
                {
                    // 次の神社→ 最寄りの寺
                    var nntera = dist(t, s[nextj]);
                    anslist.Add(Math.Abs(q - s[nextj]) + Math.Abs(nntera.Item2));
                }
                if (nextj > 0)
                {
                    // 前の神社→ 最寄りの寺
                    nextj--;
                    var nntera = dist(t, s[nextj]);
                    anslist.Add(Math.Abs(q - s[nextj]) + Math.Abs(nntera.Item2));
                }

                var nextt = Search.LowerBound(t, q);
                if (nextt < t.Length)
                {
                    // 次の寺→ 最寄りの神社
                    var nnjinja = dist(s, t[nextt]);
                    anslist.Add(Math.Abs(q - t[nextt]) + Math.Abs(nnjinja.Item2));
                }
                if (nextt > 0)
                {
                    // 前の寺→ 最寄りの神社
                    nextt--;
                    var nnjinja = dist(s, t[nextt]);
                    anslist.Add(Math.Abs(q - t[nextt]) + Math.Abs(nnjinja.Item2));
                }

                var ans = anslist.Min();
                Console.WriteLine(ans);
            }
        }

        static Tuple<int, long> dist(IList<long> list, long v)
        {
            var i = Search.LowerBound(list, v);

            var d = long.MaxValue;

            if (i < list.Count())
            {
                d = Math.Abs(v - list[i]);
            }

            if (i > 0)
            {
                var dt = Math.Abs(v - list[i - 1]);
                if (dt < d)
                {
                    d = dt;
                    i--;
                }
            }

            return new Tuple<int, long>(i, d);
        }

        /// <summary>
        /// 二分探索系
        /// </summary>
        public static class Search
        {
            /// <summary>
            /// v以上で最小のインデックスを返す
            /// </summary>
            public static int LowerBound<T>(IList<T> list, T v, int begin, int end)
                => new SearchOfComparerChangeable<T>().LowerBound(list, v, begin, end);

            /// <summary>
            /// v以上で最小のインデックスを返す
            /// </summary>
            public static int LowerBound<T>(IList<T> list, T v)
                => new SearchOfComparerChangeable<T>().LowerBound(list, v);

            /// <summary>
            /// vより大きな最小のインデックスを返す
            /// </summary>
            public static int UpperBound<T>(IList<T> list, T v, int begin, int end)
                => new SearchOfComparerChangeable<T>().UpperBound(list, v, begin, end);

            /// <summary>
            /// vより大きな最小のインデックスを返す
            /// </summary>
            public static int UpperBound<T>(IList<T> list, T v)
                => new SearchOfComparerChangeable<T>().UpperBound(list, v);

            /// <summary>
            /// 二分探索系
            /// 比較処理を外部から注入するき用
            /// </summary>
            class SearchOfComparerChangeable<T>
            {
                /// <summary> 比較用関数 </summary>
                private Comparison<T> Comparison { get; set; }

                public SearchOfComparerChangeable(Comparison<T> comparison = null)
                {
                    Comparison = comparison ?? Comparer<T>.Default.Compare;
                }

                /// <summary>
                /// Bound系の下請け
                /// </summary>
                static int FindBound(IList<T> list, T v, int begin, int end, Func<T, T, bool> judge)
                {
                    int low = begin, high = end;

                    if (low > high)
                    {
                        throw new ArgumentException($"{nameof(low)} greater than {nameof(high)}", $"{nameof(low)} and {nameof(high)}");
                    }

                    while (low < high)
                    {
                        var mid = (high + low) / 2;

                        if (judge(v, list[mid])) { high = mid; }
                        else { low = mid + 1; }
                    }

                    return low;
                }

                /// <summary>
                /// v以上で最小のインデックスを返す
                /// </summary>
                public int LowerBound(IList<T> list, T v, int begin, int end)
                    => FindBound(list, v, begin, end, (x, y) => Comparison(x, y) <= 0);

                /// <summary>
                /// v以上で最小のインデックスを返す
                /// </summary>
                public int LowerBound(IList<T> list, T v)
                {
                    if (list == null) { throw new ArgumentNullException(nameof(list)); }
                    return LowerBound(list, v, 0, list.Count);
                }

                /// <summary>
                /// vより大きな最小のインデックスを返す
                /// </summary>
                public int UpperBound(IList<T> list, T v, int begin, int end)
                    => FindBound(list, v, begin, end, (x, y) => Comparison(x, y) < 0);

                /// <summary>
                /// vより大きな最小のインデックスを返す
                /// </summary>
                public int UpperBound(IList<T> list, T v)
                {
                    if (list == null) { throw new ArgumentNullException(nameof(list)); }
                    return UpperBound(list, v, 0, list.Count);
                }

                /// <summary>
                /// 範囲中でvと等価な個数を返す
                /// </summary>
                public int EqualCount(IList<T> list, T v, int begin, int end)
                    => UpperBound(list, v, begin, end) - LowerBound(list, v, begin, end);
            }
        }

        #region Main
        public static void Main(string[] args)
        {
            // 出力が少ないときはこれをセットする方が時間かかるけれど
            // その場合は出力がボトルネックになっていないので、まあ良しとする
            var needsFlushOutput = true;
            if (needsFlushOutput)
            {
                // 細かく出力しないようにする
                var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
                Console.SetOut(sw);
            }

            // 通常は引数無しで、ファイルから読み出したい場合はpath指定する
            var input = new Input();
            // 仮想的に標準入力をセットする
            //input.SetText("");

            Solve(input);

            Console.Out.Flush();
        }
        #endregion

        #region Competitive Template
#pragma warning disable CS0414
        static readonly int MOD = (int)1e9 + 7;
        static readonly int[] dx = { 1, 0, -1, 0 };
        static readonly int[] dy = { 0, 1, 0, -1 };
        /// <summary> 左上が原点 </summary>
        static readonly char[] dir = { 'R', 'U', 'L', 'D' };
#pragma warning restore CS0414

        /// <summary>
        /// 値を書き換え可能なTuple（ぐらいのイメージ）
        /// </summary>
        public class Pair<T, U> : IComparable<Pair<T, U>>, IEquatable<Pair<T, U>>
            where T : IComparable<T>
            where U : IComparable<U>
        {
            public T V1 { get; set; }
            public U V2 { get; set; }

            public Pair(T v1, U v2)
            {
                this.V1 = v1;
                this.V2 = v2;
            }

            public Pair(Pair<T, U> src) : this(src.V1, src.V2) { }

            public int CompareTo(Pair<T, U> other)
            {
                var r = this.V1.CompareTo(other.V1);
                if (r == 0) r = this.V2.CompareTo(other.V2);

                return r;
            }

            public bool Equals(Pair<T, U> other)
                => (other != null && this.CompareTo(other) == 0);

            public override string ToString()
                => $"{V1} {V2}";

            public override bool Equals(object obj)
                => Equals(obj as Pair<T, U>);

            public override int GetHashCode()
            {
                var hashCode = 1989511945;
                hashCode = hashCode * -1521134295 + V1.GetHashCode();
                hashCode = hashCode * -1521134295 + V2.GetHashCode();
                return hashCode;
            }

            public static bool operator ==(Pair<T, U> a, Pair<T, U> b)
            {
                if (object.ReferenceEquals(a, null))
                {
                    return object.ReferenceEquals(b, null);
                }

                return a.Equals(b);
            }

            public static bool operator !=(Pair<T, U> a, Pair<T, U> b)
                => !(a == b);
            public static bool operator <(Pair<T, U> a, Pair<T, U> b)
                => a.CompareTo(b) < 0;
            public static bool operator <=(Pair<T, U> a, Pair<T, U> b)
                => a.CompareTo(b) <= 0;
            public static bool operator >(Pair<T, U> a, Pair<T, U> b)
                => a.CompareTo(b) > 0;
            public static bool operator >=(Pair<T, U> a, Pair<T, U> b)
                => a.CompareTo(b) >= 0;
        }

        public class Input
        {
            // 変な改行コードがたまに混じっているので、一応セパレート指定する
            // スペース単独指定の方がもちろん早い
            static readonly char[] separator = { ' ', '\r', '\n' };
            readonly StreamReader sr;
            readonly Queue<string> queue;

            /// <summary>
            /// 特定のファイルから読み出したい場合はpath指定する
            /// </summary>
            public Input(string path = "")
            {
                queue = new Queue<string>();

                if (string.IsNullOrEmpty(path))
                {
                    sr = new StreamReader(Console.OpenStandardInput());
                }
                else
                {
                    sr = new StreamReader(path);
                }
            }

            /// <summary>
            /// 入力予約
            /// </summary>
            public void SetText(IEnumerable<string> items)
            {
                foreach (var item in items)
                {
                    SetText(item);
                }
            }

            /// <summary>
            /// 入力予約
            /// </summary>
            public bool SetText(string s)
            {
                if (s == null) return false;

                foreach (var elem in s.Trim()
                    .Split(separator, StringSplitOptions.RemoveEmptyEntries))
                {
                    queue.Enqueue(elem);
                }

                return true;
            }

            /// <summary>
            /// 要素が存在するか
            /// </summary>
            public bool Any()
                => queue.Any() || Read();

            /// <summary>
            /// 内部queueに入力からの値をsplitして格納する
            /// </summary>
            bool Read()
            {
                if (!SetText(sr.ReadLine())) return false;

                if (!queue.Any()) return Read();

                return queue.Any();
            }

            /// <summary>
            /// 次のstringを一つ読み込む
            /// </summary>
            public string Next()
            {
                if (!queue.Any() && !Read())
                {
                    return "";
                }

                return queue.Dequeue();
            }

            /// <summary>
            /// 指定個数queueにたまるまでenqueueし続ける
            /// </summary>
            bool Accumulate(int n)
            {
                while (queue.Count() < n)
                {
                    if (!Read()) return false;
                }

                return true;
            }

            public int NextInt() => int.Parse(Next());
            public long NextLong() => long.Parse(Next());
            public double NextDouble() => double.Parse(Next());

            /// <summary>
            /// n個の要素をparseして、それぞれにoffsetをaddした配列を返す
            /// </summary>
            T[] NextT<T>(int n, T offset, Func<string, T> parse, Func<T, T, T> add)
            {
                if (!Accumulate(n)) return null;

                var a = new T[n];

                for (int i = 0; i < n; i++)
                    a[i] = add(parse(queue.Dequeue()), offset);

                return a;
            }

            public string[] Next(int n) => NextT(n, "", x => x, (x, y) => x);
            public int[] NextInt(int n, int offset = 0) => NextT(n, offset, int.Parse, (x, y) => x + y);
            public long[] NextLong(int n, long offset = 0) => NextT(n, offset, long.Parse, (x, y) => x + y);
            public double[] NextDouble(int n, double offset = 0.0) => NextT(n, offset, double.Parse, (x, y) => x + y);
        }

        static class Utils
        {
            public static void Print<T>(IEnumerable<T> ie, string sep = " ") => Console.WriteLine(string.Join(sep, ie));
            public static void Print<T>(params T[] objs) => Print(objs);
            public static T Max<T>(params T[] objs) => objs.Max();
            public static T Min<T>(params T[] objs) => objs.Min();

            public static void Swap<T>(ref T x, ref T y) where T : struct { var t = x; x = y; y = t; }
            public static void Swap<T>(IList<T> list, int i, int j) where T : struct { var t = list[i]; list[i] = list[j]; list[j] = t; }

            /// <summary>
            /// vでfillされたT[d1][d2]配列を作成する
            /// </summary>
            public static T[][] Create2DArray<T>(int d1, int d2, T v = default(T))
            {
                return
                    Enumerable.Repeat(0, d1).Select(_ =>
                    Enumerable.Repeat(v, d2).ToArray()).ToArray();
            }

            /// <summary>
            /// vでfillされたT[d1][d2][d3]配列を作成する
            /// </summary>
            public static T[][][] Create3DArray<T>(int d1, int d2, int d3, T v = default(T))
            {
                return
                    Enumerable.Repeat(0, d1).Select(_ =>
                    Enumerable.Repeat(0, d2).Select(__ =>
                    Enumerable.Repeat(v, d3).ToArray()).ToArray()).ToArray();
            }
        }
        #endregion
    }
}