Problem:
Score : 600 points

Problem Statement

There is a tree with N vertices numbered 1 to N.
The i-th edge in this tree connects Vertex a_i and Vertex b_i, and the color and length of that edge are c_i and d_i, respectively.
Here the color of each edge is represented by an integer between 1 and N-1 (inclusive). The same integer corresponds to the same color, and different integers correspond to different colors.

Answer the following Q queries:

Query j (1 \leq j \leq Q): assuming that the length of every edge whose color is x_j is changed to y_j, find the distance between Vertex u_j and Vertex v_j. (The changes of the lengths of edges do not affect the subsequent queries.)

Constraints

2 \leq N \leq 10^5

1 \leq Q \leq 10^5

1 \leq a_i, b_i \leq N

1 \leq c_i \leq N-1

1 \leq d_i \leq 10^4

1 \leq x_j \leq N-1

1 \leq y_j \leq 10^4

1 \leq u_j < v_j \leq N

The given graph is a tree.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N Q
a_1 b_1 c_1 d_1
:
a_{N-1} b_{N-1} c_{N-1} d_{N-1}
x_1 y_1 u_1 v_1
:
x_Q y_Q u_Q v_Q

Output

Print Q lines. The j-th line (1 \leq j \leq Q) should contain the answer to Query j.

Sample Input 1

5 3
1 2 1 10
1 3 2 20
2 4 4 30
5 2 1 40
1 100 1 4
1 100 1 5
3 1000 3 4

Sample Output 1

130
200
60

The graph in this input is as follows:

Here the edges of Color 1 are shown as solid red lines, the edge of Color 2 is shown as a bold green line, and the edge of Color 4 is shown as a blue dashed line.

Query 1: Assuming that the length of every edge whose color is 1 is changed to 100, the distance between Vertex 1 and Vertex 4 is 100 + 30 = 130.

Query 2: Assuming that the length of every edge whose color is 1 is changed to 100, the distance between Vertex 1 and Vertex 5 is 100 + 100 = 200.

Query 3: Assuming that the length of every edge whose color is 3 is changed to 1000 (there is no such edge), the distance between Vertex 3 and Vertex 4 is 20 + 10 + 30 = 60. Note that the edges of Color 1 now have their original lengths.

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

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using static System.Math;
using System.Text;

namespace Program
{
    public static class ABC133F
    {
        static public void Solve()
        {
            var N = NN;
            var Q = NN;
            var abcd = Repeat(0, N - 1).Select(_ => new { a = NN - 1, b = NN - 1, c = NN, d = NN }).ToArray();
            var xyuv = Repeat(0, Q).Select(_ => new { x = NN, y = NN, u = NN - 1, v = NN - 1 }).ToArray();

            var path = Repeat(0, N).Select(_ => new Dictionary<long, Tuple<long, long>>()).ToArray();
            foreach (var item in abcd)
            {
                path[item.a][item.b] = Tuple.Create(item.c, item.d);
                path[item.b][item.a] = Tuple.Create(item.c, item.d);
            }

            var tree = new Tree(path.Select(e => e.Select(e2 => e2.Key).ToList()).ToArray(), 0);
            var edgePoint = new long[N];
            var edgeSum = new long[N];
            var colorCnt = new long[N];
            var colorSum = new long[N];
            var colorRuisekiCnt = Repeat(0, N).Select(_ => new BT<Tuple<long, long>>((x, y) => x.Item1.CompareTo(y.Item1))).ToArray();
            var colorRuisekiSum = Repeat(0, N).Select(_ => new BT<Tuple<long, long>>((x, y) => x.Item1.CompareTo(y.Item1))).ToArray();
            var sum = 0L;
            var edgeNum = 0L;
            foreach (var item in tree.Euler())
            {
                if (item.Item2 == -1) continue;
                var edge = path[item.Item2][item.Item1];
                edgeNum++;
                sum += edge.Item2 * item.Item3;
                colorSum[edge.Item1] += edge.Item2 * item.Item3;
                colorCnt[edge.Item1] += item.Item3;
                if (item.Item3 == 1)
                {
                    edgeSum[item.Item1] = sum;
                    edgePoint[item.Item1] = edgeNum;
                }
                colorRuisekiCnt[edge.Item1].Add(Tuple.Create(edgeNum, colorCnt[edge.Item1]));
                colorRuisekiSum[edge.Item1].Add(Tuple.Create(edgeNum, colorSum[edge.Item1]));
            }

            foreach (var item in xyuv)
            {
                var z = tree.LCA(item.u, item.v);

                Func<long?, long> get = x => x.HasValue ? x.Value : 0;

                var sumDist = edgeSum[item.u] + edgeSum[item.v] - edgeSum[z] * 2;
                var colorCountU = colorRuisekiCnt[item.x].FindLower(Tuple.Create(edgePoint[item.u], 0L)).Item2?.Item2;
                var colorCountV = colorRuisekiCnt[item.x].FindLower(Tuple.Create(edgePoint[item.v], 0L)).Item2?.Item2;
                var colorCountZ = colorRuisekiCnt[item.x].FindLower(Tuple.Create(edgePoint[z], 0L)).Item2?.Item2;
                var colorCount = get(colorCountU) + get(colorCountV) - get(colorCountZ) * 2;
                var colorDistU = colorRuisekiSum[item.x].FindLower(Tuple.Create(edgePoint[item.u], 0L)).Item2?.Item2;
                var colorDistV = colorRuisekiSum[item.x].FindLower(Tuple.Create(edgePoint[item.v], 0L)).Item2?.Item2;
                var colorDistZ = colorRuisekiSum[item.x].FindLower(Tuple.Create(edgePoint[z], 0L)).Item2?.Item2;
                var colorDist = get(colorDistU) + get(colorDistV) - get(colorDistZ) * 2;

                Console.WriteLine(sumDist + colorCount * item.y - colorDist);
            }
        }

        static public void Main(string[] args) { if (args.Length == 0) { var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }; Console.SetOut(sw); } Solve(); Console.Out.Flush(); }
        static Random rand = new Random();
        static class Console_
        {
            static Queue<string> param = new Queue<string>();
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public static string NextString() { if (param.Count == 0) foreach (var item in Console.ReadLine().Split(' ')) param.Enqueue(item); return param.Dequeue(); }
        }
        static long NN => long.Parse(Console_.NextString());
        static double ND => double.Parse(Console_.NextString());
        static string NS => Console_.NextString();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static long[] NNList(long N) => Repeat(0, N).Select(_ => NN).ToArray();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static double[] NDList(long N) => Repeat(0, N).Select(_ => ND).ToArray();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static string[] NSList(long N) => Repeat(0, N).Select(_ => NS).ToArray();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<T> OrderByRand<T>(this IEnumerable<T> x) => x.OrderBy(_ => rand.Next());
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<T> Repeat<T>(T v, long n) => Enumerable.Repeat<T>(v, (int)n);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<int> Range(long s, long c) => Enumerable.Range((int)s, (int)c);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static void RevSort<T>(T[] l) where T : IComparable { Array.Sort(l, (x, y) => y.CompareTo(x)); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static void RevSort<T>(T[] l, Comparison<T> comp) where T : IComparable { Array.Sort(l, (x, y) => comp(y, x)); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<long> Primes(long x) { if (x < 2) yield break; yield return 2; var halfx = x / 2; var table = new bool[halfx + 1]; var max = (long)(Math.Sqrt(x) / 2); for (long i = 1; i <= max; ++i) { if (table[i]) continue; var add = 2 * i + 1; yield return add; for (long j = 2 * i * (i + 1); j <= halfx; j += add) table[j] = true; } for (long i = max + 1; i <= halfx; ++i) if (!table[i] && 2 * i + 1 <= x) yield return 2 * i + 1; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<long> Factors(long x) { if (x < 2) yield break; while (x % 2 == 0) { x /= 2; yield return 2; } var max = (long)Math.Sqrt(x); for (long i = 3; i <= max; i += 2) while (x % i == 0) { x /= i; yield return i; } if (x != 1) yield return x; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static IEnumerable<long> Divisor(long x) { if (x < 1) yield break; var max = (long)Math.Sqrt(x); for (long i = 1; i <= max; ++i) { if (x % i != 0) continue; yield return i; if (i != x / i) yield return x / i; } }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static long GCD(long a, long b) { while (b > 0) { var tmp = b; b = a % b; a = tmp; } return a; }
        static long LCM(long a, long b) => a * b / GCD(a, b);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static Mat<T> Pow<T>(Mat<T> x, long y) => Mat<T>.Pow(x, y);
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static T Pow<T>(T x, long y) { T a = (dynamic)1; while (y != 0) { if ((y & 1) == 1) a *= (dynamic)x; x *= (dynamic)x; y >>= 1; } return a; }
        static List<long> _fact = new List<long>() { 1 };
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static void _B(long n) { if (n >= _fact.Count) for (int i = _fact.Count; i <= n; ++i) _fact.Add(_fact[i - 1] * i); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static long Comb(long n, long k) { _B(n); if (n == 0 && k == 0) return 1; if (n < k || n < 0) return 0; return _fact[(int)n] / _fact[(int)(n - k)] / _fact[(int)k]; }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static long Perm(long n, long k) { _B(n); if (n == 0 && k == 0) return 1; if (n < k || n < 0) return 0; return _fact[(int)n] / _fact[(int)(n - k)]; }
        class PQ<T> where T : IComparable
        {
            List<T> h; Comparison<T> c; public T Peek => h[0]; public int Count => h.Count;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(int cap, Comparison<T> c, bool asc = true) { h = new List<T>(cap); this.c = asc ? c : (x, y) => c(y, x); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(Comparison<T> c, bool asc = true) { h = new List<T>(); this.c = asc ? c : (x, y) => c(y, x); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(int cap, bool asc = true) : this(cap, (x, y) => x.CompareTo(y), asc) { }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(bool asc = true) : this((x, y) => x.CompareTo(y), asc) { }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void Push(T v) { var i = h.Count; h.Add(v); while (i > 0) { var ni = (i - 1) / 2; if (c(v, h[ni]) >= 0) break; h[i] = h[ni]; i = ni; } h[i] = v; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public T Pop() { var r = h[0]; var v = h[h.Count - 1]; h.RemoveAt(h.Count - 1); if (h.Count == 0) return r; var i = 0; while (i * 2 + 1 < h.Count) { var i1 = i * 2 + 1; var i2 = i * 2 + 2; if (i2 < h.Count && c(h[i1], h[i2]) > 0) i1 = i2; if (c(v, h[i1]) <= 0) break; h[i] = h[i1]; i = i1; } h[i] = v; return r; }
        }
        class PQ<TK, TV> where TK : IComparable
        {
            PQ<Tuple<TK, TV>> q; public Tuple<TK, TV> Peek => q.Peek; public int Count => q.Count;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(int cap, Comparison<TK> c, bool asc = true) { q = new PQ<Tuple<TK, TV>>(cap, (x, y) => c(x.Item1, y.Item1), asc); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(Comparison<TK> c, bool asc = true) { q = new PQ<Tuple<TK, TV>>((x, y) => c(x.Item1, y.Item1), asc); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(int cap, bool asc = true) : this(cap, (x, y) => x.CompareTo(y), asc) { }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public PQ(bool asc = true) : this((x, y) => x.CompareTo(y), asc) { }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void Push(TK k, TV v) => q.Push(Tuple.Create(k, v));
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<TK, TV> Pop() => q.Pop();
        }
        public class UF
        {
            long[] d;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public UF(long s) { d = Repeat(-1L, s).ToArray(); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool Unite(long x, long y) { x = Root(x); y = Root(y); if (x != y) { if (d[y] < d[x]) { var t = y; y = x; x = t; } d[x] += d[y]; d[y] = x; } return x != y; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool IsSame(long x, long y) => Root(x) == Root(y);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public long Root(long x) => d[x] < 0 ? x : d[x] = Root(d[x]);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public long Count(long x) => -d[Root(d[x])];
        }
        struct Mod : IEquatable<object>
        {
            static public long _mod = 1000000007; long _val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Mod(long x) { if (x < _mod && x >= 0) _val = x; else if ((_val = x % _mod) < 0) _val += _mod; }
            static public implicit operator Mod(long x) => new Mod(x);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public implicit operator long(Mod x) => x._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod operator +(Mod x, Mod y) => x._val + y._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod operator -(Mod x, Mod y) => x._val - y._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod operator *(Mod x, Mod y) => x._val * y._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod operator /(Mod x, Mod y) => x._val * Inverse(y._val);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public bool operator ==(Mod x, Mod y) => x._val == y._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public bool operator !=(Mod x, Mod y) => x._val != y._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public long Inverse(long x) { long b = _mod, r = 1, u = 0, t = 0; while (b > 0) { var q = x / b; t = u; u = r - q * u; r = t; t = b; b = x - q * b; x = t; } return r < 0 ? r + _mod : r; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            bool IEquatable<object>.Equals(object obj) => obj == null ? false : Equals((Mod)obj);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public override bool Equals(object obj) => obj == null ? false : Equals((Mod)obj);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool Equals(Mod obj) => obj == null ? false : _val == obj._val;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public override int GetHashCode() => _val.GetHashCode();
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public override string ToString() => _val.ToString();
            static List<Mod> _fact = new List<Mod>() { 1 };
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static void B(long n) { if (n >= _fact.Count) for (int i = _fact.Count; i <= n; ++i) _fact.Add(_fact[i - 1] * i); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod Comb(long n, long k) { B(n); if (n == 0 && k == 0) return 1; if (n < k || n < 0) return 0; return _fact[(int)n] / _fact[(int)(n - k)] / _fact[(int)k]; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mod Perm(long n, long k) { B(n); if (n == 0 && k == 0) return 1; if (n < k || n < 0) return 0; return _fact[(int)n] / _fact[(int)(n - k)]; }
        }
        struct Mat<T>
        {
            T[,] m;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Mat(T[,] v) { m = (T[,])v.Clone(); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public implicit operator Mat<T>(T[,] v) => new Mat<T>(v);
            public T this[int r, int c] { get { return m[r, c]; } set { m[r, c] = value; } }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator +(Mat<T> a, T x) { var tm = (T[,])a.m.Clone(); for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] += (dynamic)x; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator +(Mat<T> a, Mat<T> b) { var tm = (T[,])a.m.Clone(); for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] += (dynamic)b[r, c]; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator -(Mat<T> a, T x) { var tm = (T[,])a.m.Clone(); for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] -= (dynamic)x; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator -(Mat<T> a, Mat<T> b) { var tm = (T[,])a.m.Clone(); for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] -= (dynamic)b[r, c]; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator *(Mat<T> a, T x) { var tm = (T[,])a.m.Clone(); for (int r = 0; r < tm.GetLength(0); ++r) for (int c = 0; c < tm.GetLength(1); ++c) tm[r, c] *= (dynamic)x; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> operator *(Mat<T> a, Mat<T> b) { var nr = a.m.GetLength(0); var nc = b.m.GetLength(1); var tm = new T[nr, nc]; for (int i = 0; i < nr; ++i) for (int j = 0; j < nc; ++j) tm[i, j] = (dynamic)0; for (int r = 0; r < nr; ++r) for (int c = 0; c < nc; ++c) for (int i = 0; i < a.m.GetLength(1); ++i) tm[r, c] += a[r, i] * (dynamic)b[i, c]; return tm; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static public Mat<T> Pow(Mat<T> x, long y) { var n = x.m.GetLength(0); var t = (Mat<T>)new T[n, n]; for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) t[i, j] = (dynamic)(i == j ? 1 : 0); while (y != 0) { if ((y & 1) == 1) t *= x; x *= x; y >>= 1; } return t; }
        }
        class Tree
        {
            long N; int l; List<long>[] p; int[] d; long[][] pr; long r; Tuple<long, long, int>[] e; Tuple<long, long>[] b; bool lca; bool euler; bool bfs;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tree(List<long>[] p_, long r_) { N = p_.Length; p = p_; r = r_; lca = false; euler = false; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<long, long>[] FromRoot() { if (!bfs) { var nb = new List<Tuple<long, long>>(); var q = new Queue<long>(); var d = new bool[N]; nb.Add(Tuple.Create(r, -1L)); d[r] = true; q.Enqueue(r); while (q.Count > 0) { var w = q.Dequeue(); foreach (var i in p[w]) { if (d[i]) continue; d[i] = true; q.Enqueue(i); nb.Add(Tuple.Create(i, w)); } } b = nb.ToArray(); bfs = true; } return b; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<long, long>[] FromLeaf() => FromRoot().Reverse().ToArray();
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<long, long, int>[] Euler() { if (!euler) { var ne = new List<Tuple<long, long, int>>(); var s = new Stack<Tuple<long, long>>(); var d = new bool[N]; d[r] = true; s.Push(Tuple.Create(r, -1L)); while (s.Count > 0) { var w = s.Peek(); var ad = true; foreach (var i in p[w.Item1]) { if (d[i]) continue; d[i] = true; ad = false; s.Push(Tuple.Create(i, w.Item1)); } if (!ad || p[w.Item1].Count == 1) ne.Add(Tuple.Create(w.Item1, w.Item2, 1)); if (ad) { s.Pop(); ne.Add(Tuple.Create(w.Item1, w.Item2, -1)); } } e = ne.ToArray(); euler = true; } return e; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public long LCA(long u, long v) { if (!lca) { l = 0; while (N > (1 << l)) l++; d = new int[N]; pr = Repeat(0, l).Select(_ => new long[N]).ToArray(); d[r] = 0; pr[0][r] = -1; var q = new Stack<long>(); q.Push(r); while (q.Count > 0) { var w = q.Pop(); foreach (var i in p[w]) { if (i == pr[0][w]) continue; q.Push(i); d[i] = d[w] + 1; pr[0][i] = w; } } for (var k = 0; k + 1 < l; k++) for (var w = 0; w < N; w++) if (pr[k][w] < 0) pr[k + 1][w] = -1; else pr[k + 1][w] = pr[k][pr[k][w]]; lca = true; } if (d[u] > d[v]) { var t = u; u = v; v = t; } for (var k = 0; k < l; k++) if ((((d[v] - d[u]) >> k) & 1) != 0) v = pr[k][v]; if (u == v) return u; for (var k = l - 1; k >= 0; k--) if (pr[k][u] != pr[k][v]) { u = pr[k][u]; v = pr[k][v]; } return pr[0][u]; }
        }
        class BT<T> where T : IComparable
        {
            class Node { public Node l; public Node r; public T v; public bool b; }
            Comparison<T> c; Node r; bool ch; T lm;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public BT(Comparison<T> _c) { c = _c; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public BT() : this((x, y) => x.CompareTo(y)) { }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            bool R(Node n) => n != null && !n.b;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            bool B(Node n) => n != null && n.b;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node RtL(Node n) { Node m = n.r, t = m.l; m.l = n; n.r = t; return m; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node RtR(Node n) { Node m = n.l, t = m.r; m.r = n; n.l = t; return m; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node RtLR(Node n) { n.l = RtL(n.l); return RtR(n); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node RtRL(Node n) { n.r = RtR(n.r); return RtL(n); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void Add(T x) { r = A(r, x); r.b = true; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node A(Node n, T x) { if (n == null) { ch = true; return new Node() { v = x }; } var r = c(x, n.v); if (r < 0) { n.l = A(n.l, x); return Bl(n); } if (r > 0) { n.r = A(n.r, x); return Bl(n); } ch = false; return n; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node Bl(Node n) { if (!ch) return n; if (!B(n)) return n; if (R(n.l) && R(n.l.l)) { n = RtR(n); n.l.b = true; } else if (R(n.l) && R(n.l.r)) { n = RtLR(n); n.l.b = true; } else if (R(n.r) && R(n.r.l)) { n = RtRL(n); n.r.b = true; } else if (R(n.r) && R(n.r.r)) { n = RtL(n); n.r.b = true; } else ch = false; return n; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public void Remove(T x) { r = Rm(r, x); if (r != null) r.b = true; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node Rm(Node n, T x) { if (n == null) { ch = false; return n; } var r = c(x, n.v); if (r < 0) { n.l = Rm(n.l, x); return BlL(n); } if (r > 0) { n.r = Rm(n.r, x); return BlR(n); } if (n.l == null) { ch = n.b; return n.r; } n.l = RmM(n.l); n.v = lm; return BlL(n); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node RmM(Node n) { if (n.r != null) { n.r = RmM(n.r); return BlR(n); } lm = n.v; ch = n.b; return n.l; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node BlL(Node n) { if (!ch) return n; if (B(n.r) && R(n.r.l)) { var b = n.b; n = RtRL(n); n.b = b; n.l.b = true; ch = false; } else if (B(n.r) && R(n.r.r)) { var b = n.b; n = RtL(n); n.b = b; n.r.b = true; n.l.b = true; ch = false; } else if (B(n.r)) { ch = n.b; n.b = true; n.r.b = false; } else { n = RtL(n); n.b = true; n.l.b = false; n.l = BlL(n.l); ch = false; } return n; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Node BlR(Node n) { if (!ch) return n; if (B(n.l) && R(n.l.r)) { var b = n.b; n = RtLR(n); n.b = b; n.r.b = true; ch = false; } else if (B(n.l) && R(n.l.l)) { var b = n.b; n = RtR(n); n.b = b; n.l.b = true; n.r.b = true; ch = false; } else if (B(n.l)) { ch = n.b; n.b = true; n.l.b = false; } else { n = RtR(n); n.b = true; n.r.b = false; n.r = BlR(n.r); ch = false; } return n; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool Have(T x) { var t = FindUpper(x); return t.Item1 && t.Item2.CompareTo(x) == 0; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<bool, T> FindUpper(T x) { var v = FU(r, x); return v == null ? Tuple.Create(false, default(T)) : v; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Tuple<bool, T> FU(Node n, T x) { if (n == null) return null; var r = c(x, n.v); if (r < 0) { var v = FU(n.l, x); return v == null ? Tuple.Create(true, n.v) : v; } if (r > 0) return FU(n.r, x); return Tuple.Create(true, n.v); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public Tuple<bool, T> FindLower(T x) { var v = FL(r, x); return v == null ? Tuple.Create(false, default(T)) : v; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            Tuple<bool, T> FL(Node n, T x) { if (n == null) return null; var r = c(x, n.v); if (r < 0) return FL(n.l, x); if (r > 0) { var v = FL(n.r, x); return v == null ? Tuple.Create(true, n.v) : v; } return Tuple.Create(true, n.v); }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public T Min() { Node n = r, p = null; while (n != null) { p = n; n = n.l; } return p == null ? default(T) : p.v; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public T Max() { Node n = r, p = null; while (n != null) { p = n; n = n.r; } return p == null ? default(T) : p.v; }
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public bool Any() => r != null;
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public int CountSlow() => L(r).Count();
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            public IEnumerable<T> List() => L(r);
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            IEnumerable<T> L(Node n) { if (n == null) yield break; foreach (var i in L(n.l)) yield return i; yield return n.v; foreach (var i in L(n.r)) yield return i; }
        }
    }
}