結果
問題 | No.2360 Path to Integer |
ユーザー | yupiteru_kun |
提出日時 | 2023-06-23 21:47:50 |
言語 | C# (.NET 8.0.203) |
結果 |
AC
|
実行時間 | 954 ms / 2,500 ms |
コード長 | 32,067 bytes |
コンパイル時間 | 16,448 ms |
コンパイル使用メモリ | 171,176 KB |
実行使用メモリ | 279,520 KB |
最終ジャッジ日時 | 2024-07-01 01:23:24 |
合計ジャッジ時間 | 25,470 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 71 ms
31,720 KB |
testcase_01 | AC | 71 ms
31,616 KB |
testcase_02 | AC | 71 ms
31,616 KB |
testcase_03 | AC | 71 ms
32,128 KB |
testcase_04 | AC | 71 ms
31,616 KB |
testcase_05 | AC | 71 ms
31,488 KB |
testcase_06 | AC | 73 ms
31,488 KB |
testcase_07 | AC | 79 ms
33,280 KB |
testcase_08 | AC | 162 ms
46,336 KB |
testcase_09 | AC | 949 ms
134,248 KB |
testcase_10 | AC | 894 ms
136,532 KB |
testcase_11 | AC | 896 ms
136,552 KB |
testcase_12 | AC | 660 ms
133,860 KB |
testcase_13 | AC | 954 ms
133,852 KB |
testcase_14 | AC | 862 ms
133,800 KB |
testcase_15 | AC | 954 ms
136,340 KB |
testcase_16 | AC | 835 ms
279,520 KB |
コンパイルメッセージ
復元対象のプロジェクトを決定しています... /home/judge/data/code/main.csproj を復元しました (102 ms)。 MSBuild のバージョン 17.9.6+a4ecab324 (.NET) main -> /home/judge/data/code/bin/Release/net8.0/main.dll main -> /home/judge/data/code/bin/Release/net8.0/publish/
ソースコード
using System; using System.Collections.Generic; using System.IO; using System.Linq; using static System.Math; using System.Text; using System.Threading; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Library; namespace Program { public static class ProblemA { static bool SAIKI = false; static public int numberOfRandomCases = 0; static public void MakeTestCase(List<string> _input, List<string> _output, ref Func<string[], bool> _outputChecker) { } static public void Solve() { var N = NN; var AList = NSList(N); var uv = Repeat(0, N - 1).Select(_ => new { u = NN - 1, v = NN - 1 }).ToArray(); var tree = new LIB_Tree(N); foreach (var item in uv) { tree.AddPath(item.u, item.v); } var dp = tree.LIB_ReRooting<(LIB_Mod998244353 keta, LIB_Mod998244353 val)>() .MergeSubtrees((s, t) => { return (s.keta + t.keta, s.val + t.val); }).MergeVertexAndSubtree((v, s) => { return (s.keta * v.keta + v.keta, s.keta * v.val + v.val + s.val); }).VertexToValue(idx => { return (LIB_Mod998244353.Pow(10, AList[idx].Length), long.Parse(AList[idx])); }).Build(); LIB_Mod998244353 ans = 0; for (var i = 0; i < N; ++i) { ans += dp[i, -1].val; } Console.WriteLine(ans); } class Printer : StreamWriter { public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } } public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { base.AutoFlush = false; } public Printer(Stream stream, Encoding encoding) : base(stream, encoding) { base.AutoFlush = false; } } static LIB_FastIO fastio = new LIB_FastIODebug(); static string[] args; static public void Main(string[] args_t) { args = args_t; if (args_t.Length == 0) { fastio = new LIB_FastIO(); Console.SetOut(new Printer(Console.OpenStandardOutput())); } if (SAIKI) { var t = new Thread(Solve, 134217728); t.Start(); t.Join(); } else Solve(); Console.Out.Flush(); } static long NN => fastio.Long(); static double ND => fastio.Double(); static string NS => fastio.Scan(); static long[] NNList(long N) => Repeat(0, N).Select(_ => NN).ToArray(); static double[] NDList(long N) => Repeat(0, N).Select(_ => ND).ToArray(); static string[] NSList(long N) => Repeat(0, N).Select(_ => NS).ToArray(); static long Count<T>(this IEnumerable<T> x, Func<T, bool> pred) => Enumerable.Count(x, pred); static IEnumerable<T> Repeat<T>(T v, long n) => Enumerable.Repeat<T>(v, (int)n); static IEnumerable<int> Range(long s, long c) => Enumerable.Range((int)s, (int)c); static IOrderedEnumerable<T> OrderByRand<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x, _ => xorshift); static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x.OrderByRand(), e => e); static IOrderedEnumerable<T1> OrderBy<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderBy(x.OrderByRand(), selector); static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x) => Enumerable.OrderByDescending(x.OrderByRand(), e => e); static IOrderedEnumerable<T1> OrderByDescending<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderByDescending(x.OrderByRand(), selector); static IOrderedEnumerable<string> OrderBy(this IEnumerable<string> x) => x.OrderByRand().OrderBy(e => e, StringComparer.OrdinalIgnoreCase); static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderBy(selector, StringComparer.OrdinalIgnoreCase); static IOrderedEnumerable<string> OrderByDescending(this IEnumerable<string> x) => x.OrderByRand().OrderByDescending(e => e, StringComparer.OrdinalIgnoreCase); static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderByDescending(selector, StringComparer.OrdinalIgnoreCase); static string Join<T>(this IEnumerable<T> x, string separator = "") => string.Join(separator, x); static uint xorshift { get { _xsi.MoveNext(); return _xsi.Current; } } static IEnumerator<uint> _xsi = _xsc(); static IEnumerator<uint> _xsc() { uint x = 123456789, y = 362436069, z = 521288629, w = (uint)(DateTime.Now.Ticks & 0xffffffff); while (true) { var t = x ^ (x << 11); x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); yield return w; } } static bool Chmax<T>(this ref T lhs, T rhs) where T : struct, IComparable<T> { if (lhs.CompareTo(rhs) < 0) { lhs = rhs; return true; } return false; } static bool Chmin<T>(this ref T lhs, T rhs) where T : struct, IComparable<T> { if (lhs.CompareTo(rhs) > 0) { lhs = rhs; return true; } return false; } static void Fill<T>(this T[] array, T value) => array.AsSpan().Fill(value); static void Fill<T>(this T[,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0], array.Length).Fill(value); static void Fill<T>(this T[,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0], array.Length).Fill(value); static void Fill<T>(this T[,,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0, 0], array.Length).Fill(value); } } namespace Library { partial class LIB_Tree { int N; List<int>[] path; Dictionary<int, int>[] pathWithCount; List<(int u, int v)> edges; [MethodImpl(MethodImplOptions.AggressiveInlining)] public LIB_Tree(long n) { N = (int)n; path = Enumerable.Repeat(0, N).Select(_ => new List<int>()).ToArray(); pathWithCount = Enumerable.Repeat(0, N).Select(_ => new Dictionary<int, int>()).ToArray(); edges = new List<(int u, int v)>(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddPath(long u, long v) { if (u >= N || v >= N) throw new Exception(); path[u].Add((int)v); path[v].Add((int)u); pathWithCount[u].Add((int)v, edges.Count); pathWithCount[v].Add((int)u, edges.Count); edges.Add(((int)u, (int)v)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int[] GetSurround(long u) => path[u].ToArray(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public List<(long node, long parent)> BFSFromRoot(long root) { var bfsList = new List<(long node, long parent)>(); var q = new Queue<int>(); var done = new bool[N]; bfsList.Add((root, -1)); done[root] = true; q.Enqueue((int)root); while (q.Count > 0) { var w = q.Dequeue(); foreach (var edge in pathWithCount[w]) { var i = edge.Key; if (done[i]) continue; done[i] = true; q.Enqueue(i); bfsList.Add((i, w)); } } return bfsList; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public long[] GetDistanceFrom(long root) { var ret = new long[N]; foreach (var item in BFSFromRoot(root)) { if (item.parent == -1) continue; ret[item.node] = ret[item.parent] + 1; } return ret; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int[] GetJuusin() { var center = new List<int>(); var dp = new long[N]; foreach (var item in BFSFromLeaf(0)) { dp[item.node] += 1; var ok = false; foreach (var edge in path[item.node]) { var idx = edge; if (idx == item.parent) continue; dp[item.node] += dp[idx]; if (dp[idx] <= N / 2) ok = true; } if (ok) { if (N - dp[item.node] <= N / 2) { center.Add((int)item.node); } } } return center.ToArray(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int[] GetTyokkei() { var dist1 = GetDistanceFrom(0); var maxPos = 0; var maxDist = 0L; for (var i = 0; i < N; i++) { if (maxDist < dist1[i]) { maxDist = dist1[i]; maxPos = i; } } var dist2 = new int[N]; var parent = new int[N]; maxDist = 0; var anotherMaxPos = 0L; foreach (var item in BFSFromRoot(maxPos)) { parent[item.node] = (int)item.parent; if (item.parent == -1) continue; dist2[item.node] = dist2[item.parent] + 1; if (maxDist < dist2[item.node]) { maxDist = dist2[item.node]; anotherMaxPos = item.node; } } var nownode = (int)anotherMaxPos; var ret = new List<int>(); while (nownode != -1) { ret.Add(nownode); nownode = parent[nownode]; } return ret.ToArray(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public List<(long node, long parent)> BFSFromLeaf(long root) => BFSFromRoot(root).ToArray().Reverse().ToList(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public (long node, long parent, long direction)[] EulerTour(long root) { var eulerList = new (long node, long parent, long direction)[N << 1]; ref var eulerListRef = ref eulerList[0]; var stack = new int[N << 1]; ref var stackref = ref stack[0]; var si = 0; Unsafe.Add(ref stackref, si++) = (int)root + 1; var idx = 0; var par = new int[N]; ref var parref = ref par[0]; Unsafe.Add(ref parref, (int)root) = -1; while (si > 0) { var vtx = Unsafe.Add(ref stackref, --si); if (vtx < 0) { vtx *= -1; --vtx; Unsafe.Add(ref eulerListRef, idx) = (vtx, Unsafe.Add(ref parref, vtx), -1); } else { Unsafe.Add(ref stackref, si++) = -vtx; --vtx; var pare = Unsafe.Add(ref parref, vtx); Unsafe.Add(ref eulerListRef, idx) = (vtx, pare, 1); foreach (var edge in path[vtx]) { var item = edge; if (item == pare) continue; Unsafe.Add(ref parref, item) = vtx; Unsafe.Add(ref stackref, si++) = item + 1; } } ++idx; } return eulerList; } } partial struct LIB_Mod998244353 : IEquatable<LIB_Mod998244353>, IEquatable<long> { const int _mod = 998244353; long v; [MethodImpl(MethodImplOptions.AggressiveInlining)] public LIB_Mod998244353(long x) { if (x < _mod && x >= 0) v = x; else if ((v = x % _mod) < 0) v += _mod; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static public implicit operator LIB_Mod998244353(long x) => new LIB_Mod998244353(x); [MethodImpl(MethodImplOptions.AggressiveInlining)] static public implicit operator long(LIB_Mod998244353 x) => x.v; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(LIB_Mod998244353 x) { if ((v += x.v) >= _mod) v -= _mod; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Sub(LIB_Mod998244353 x) { if ((v -= x.v) < 0) v += _mod; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Mul(LIB_Mod998244353 x) => v = (v * x.v) % _mod; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Div(LIB_Mod998244353 x) => v = (v * Inverse(x.v)) % _mod; [MethodImpl(MethodImplOptions.AggressiveInlining)] static public LIB_Mod998244353 operator +(LIB_Mod998244353 x, LIB_Mod998244353 y) { var t = x.v + y.v; return t >= _mod ? new LIB_Mod998244353 { v = t - _mod } : new LIB_Mod998244353 { v = t }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static public LIB_Mod998244353 operator -(LIB_Mod998244353 x, LIB_Mod998244353 y) { var t = x.v - y.v; return t < 0 ? new LIB_Mod998244353 { v = t + _mod } : new LIB_Mod998244353 { v = t }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static public LIB_Mod998244353 operator *(LIB_Mod998244353 x, LIB_Mod998244353 y) => x.v * y.v; [MethodImpl(MethodImplOptions.AggressiveInlining)] static public LIB_Mod998244353 operator /(LIB_Mod998244353 x, LIB_Mod998244353 y) => x.v * Inverse(y.v); [MethodImpl(MethodImplOptions.AggressiveInlining)] static public bool operator ==(LIB_Mod998244353 x, LIB_Mod998244353 y) => x.v == y.v; [MethodImpl(MethodImplOptions.AggressiveInlining)] static public bool operator !=(LIB_Mod998244353 x, LIB_Mod998244353 y) => x.v != y.v; [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)] public bool Equals(LIB_Mod998244353 x) => v == x.v; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(long x) => v == x; [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(object x) => x == null ? false : Equals((LIB_Mod998244353)x); [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() => v.GetHashCode(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public override string ToString() => v.ToString(); static List<LIB_Mod998244353> _fact = new List<LIB_Mod998244353>() { 1, 1 }; static List<LIB_Mod998244353> _inv = new List<LIB_Mod998244353>() { 0, 1 }; static List<LIB_Mod998244353> _factinv = new List<LIB_Mod998244353>() { 1, 1 }; static long _factm = _mod; [MethodImpl(MethodImplOptions.AggressiveInlining)] static void B(long n) { if (_factm != _mod) { _fact = new List<LIB_Mod998244353>() { 1, 1 }; _inv = new List<LIB_Mod998244353>() { 0, 1 }; _factinv = new List<LIB_Mod998244353>() { 1, 1 }; } if (n >= _fact.Count) { for (int i = _fact.Count; i <= n; ++i) { _fact.Add(_fact[i - 1] * i); _inv.Add(_mod - _inv[(int)(_mod % i)] * (_mod / i)); _factinv.Add(_factinv[i - 1] * _inv[i]); } } _factm = _mod; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static public LIB_Mod998244353 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] * _factinv[(int)(n - k)] * _factinv[(int)k]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static public LIB_Mod998244353 CombOK(long n, long k) { LIB_Mod998244353 ret = 1; LIB_Mod998244353 deno = 1; var chk = n - k; if (chk < k) k = chk; for (var i = 0; i < k; i++) ret *= n - i; for (var i = 1; i <= k; i++) deno *= i; return ret / deno; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static public LIB_Mod998244353 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] * _factinv[(int)(n - k)]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static public LIB_Mod998244353 KanzenPerm(long n, long k) => Enumerable.Range(0, (int)k + 1).Aggregate((LIB_Mod998244353)0, (a, e) => a + (1 - ((e & 1) << 1)) * LIB_Mod998244353.Comb(k, e) * LIB_Mod998244353.Perm(n - e, k - e)); [MethodImpl(MethodImplOptions.AggressiveInlining)] static public LIB_Mod998244353 Pow(LIB_Mod998244353 x, long y) { LIB_Mod998244353 a = 1; while (y != 0) { if ((y & 1) == 1) a.Mul(x); x.Mul(x); y >>= 1; } return a; } } class LIB_FastIO { [MethodImpl(MethodImplOptions.AggressiveInlining)] public LIB_FastIO() { str = Console.OpenStandardInput(); } readonly Stream str; readonly byte[] buf = new byte[2048]; int len, ptr; [MethodImpl(MethodImplOptions.AggressiveInlining)] byte read() { if (ptr >= len) { ptr = 0; if ((len = str.Read(buf, 0, 2048)) <= 0) { return 0; } } return buf[ptr++]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] char Char() { byte b = 0; do b = read(); while (b < 33 || 126 < b); return (char)b; } [MethodImpl(MethodImplOptions.AggressiveInlining)] virtual public string Scan() { var sb = new StringBuilder(); for (var b = Char(); b >= 33 && b <= 126; b = (char)read()) sb.Append(b); return sb.ToString(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] virtual public long Long() { long ret = 0; byte b = 0; var ng = false; do b = read(); while (b != '-' && (b < '0' || '9' < b)); if (b == '-') { ng = true; b = read(); } for (; true; b = read()) { if (b < '0' || '9' < b) return ng ? -ret : ret; else ret = (ret << 3) + (ret << 1) + b - '0'; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] virtual public double Double() { return double.Parse(Scan(), CultureInfo.InvariantCulture); } } class LIB_FastIODebug : LIB_FastIO { Queue<string> param = new Queue<string>(); [MethodImpl(MethodImplOptions.AggressiveInlining)] string NextString() { if (param.Count == 0) foreach (var item in Console.ReadLine().Split(' ')) param.Enqueue(item); return param.Dequeue(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public LIB_FastIODebug() { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public override string Scan() => NextString(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public override long Long() => long.Parse(NextString()); [MethodImpl(MethodImplOptions.AggressiveInlining)] public override double Double() => double.Parse(NextString()); } // copy key class LIB_ReRooting partial class /* not copy key */ LIB_Tree { /// <summary> /// 全方位木DP /// </summary> /// <returns>2次元配列[node, parent]の部分木のDP値。parent=-1はnodeをルートとした木の値</returns> [MethodImpl(MethodImplOptions.AggressiveInlining)] public CReRooting<T> LIB_ReRooting<T>() => new CReRooting<T>(this); public class CReRooting<T> { LIB_Tree tree; Dictionary<int, T>[] dp; Func<T, T, T> f; Func<long, T> g; Func<long, long, T, T> g2; Func<T, T, T> h; [MethodImpl(MethodImplOptions.AggressiveInlining)] public CReRooting(LIB_Tree tree) { this.tree = tree; dp = Enumerable.Repeat(0, tree.N).Select(_ => new Dictionary<int, T>()).ToArray(); f = (x, y) => throw new NotImplementedException(); g = v => throw new NotImplementedException(); g2 = (r, p, v) => v; h = (v, t) => t; } public T this[long vtx, long parent] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return dp[vtx][(int)parent]; } } /// <summary> /// 部分木と部分木のマージ(subtree, subtree)するメソッドを設定 /// </summary> [MethodImpl(MethodImplOptions.AggressiveInlining)] public CReRooting<T> MergeSubtrees(Func<T, T, T> mergeSubTrees) { f = mergeSubTrees; return this; } /// <summary> /// 頂点番号から値を取得するメソッドを設定 /// </summary> [MethodImpl(MethodImplOptions.AggressiveInlining)] public CReRooting<T> VertexToValue(Func<long, T> idxToVal) { g = idxToVal; return this; } /// <summary> /// 頂点番号(root, parent)で表す辺とrootをルートとする部分木をマージするメソッドを設定 /// </summary> [MethodImpl(MethodImplOptions.AggressiveInlining)] public CReRooting<T> MergeEdgeAndSubtree(Func<long, long, T, T> mergeEdgeAndSubtree) { g2 = mergeEdgeAndSubtree; return this; } /// <summary> /// 頂点と部分木の結果をマージ(vertex, subtrees)するメソッドを設定 /// </summary> [MethodImpl(MethodImplOptions.AggressiveInlining)] public CReRooting<T> MergeVertexAndSubtree(Func<T, T, T> mergeVertexAndSubtree) { h = mergeVertexAndSubtree; return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public CReRooting<T> Build() { var done = new bool[tree.N]; Action<long, long, T> upd = (vtx, rt, val) => { if (vtx == -1) return; if (done[vtx]) dp[vtx][-1] = f(dp[vtx][-1], g2(rt, vtx, val)); else dp[vtx][-1] = g2(rt, vtx, val); done[vtx] = true; }; foreach (var item in tree.BFSFromLeaf(0)) { var ary = tree.path[item.node].Where(e => e != item.parent).ToArray(); var val = g(item.node); if (ary.Length > 0) { var acc = g2(ary[0], item.node, dp[ary[0]][(int)item.node]); foreach (var item2 in ary.Skip(1)) acc = f(acc, g2(item2, item.node, dp[item2][(int)item.node])); val = h(val, acc); } upd(item.parent, item.node, dp[item.node][(int)item.parent] = val); } var swag = new LIB_SlidingWindowAggregation<T>(f); Action<int, int> process = (node, parent) => { var val = g(node); if (tree.path[node].Count == 1) { var x = tree.path[node][0]; if (x != parent) upd(x, node, dp[node][x] = val); } else if (tree.path[node].Count == 2) { var x = tree.path[node][0]; var y = tree.path[node][1]; if (x != parent) upd(x, node, dp[node][x] = h(val, g2(y, node, dp[y][node]))); if (y != parent) upd(y, node, dp[node][y] = h(val, g2(x, node, dp[x][node]))); } else if (tree.path[node].Count == 3) { var x = tree.path[node][0]; var y = tree.path[node][1]; var z = tree.path[node][2]; if (x != parent) upd(x, node, dp[node][x] = h(val, f(g2(y, node, dp[y][node]), g2(z, node, dp[z][node])))); if (y != parent) upd(y, node, dp[node][y] = h(val, f(g2(x, node, dp[x][node]), g2(z, node, dp[z][node])))); if (z != parent) upd(z, node, dp[node][z] = h(val, f(g2(x, node, dp[x][node]), g2(y, node, dp[y][node])))); } else if (tree.path[node].Count == 4) { var x = tree.path[node][0]; var y = tree.path[node][1]; var z = tree.path[node][2]; var w = tree.path[node][3]; var xy = f(g2(x, node, dp[x][node]), g2(y, node, dp[y][node])); var zw = f(g2(z, node, dp[z][node]), g2(w, node, dp[w][node])); if (x != parent) upd(x, node, dp[node][x] = h(val, f(g2(y, node, dp[y][node]), zw))); if (y != parent) upd(y, node, dp[node][y] = h(val, f(g2(x, node, dp[x][node]), zw))); if (z != parent) upd(z, node, dp[node][z] = h(val, f(xy, g2(w, node, dp[w][node])))); if (w != parent) upd(w, node, dp[node][w] = h(val, f(xy, g2(z, node, dp[z][node])))); } else { swag.Clear(); var pre = new T[tree.path[node].Count]; for (var i = 0; i < pre.Length; ++i) swag.PushBack(pre[i] = g2(tree.path[node][i], node, dp[tree.path[node][i]][node])); for (var i = 0; i < pre.Length; ++i) { var item2 = tree.path[node][i]; swag.PopFront(); if (item2 != parent) upd(item2, node, dp[node][item2] = h(val, swag.Aggregate())); swag.PushBack(pre[i]); } } }; foreach (var item in tree.BFSFromRoot(0)) process((int)item.node, (int)item.parent); for (var i = 1; i < tree.N; i++) dp[i][-1] = done[i] ? h(g(i), dp[i][-1]) : g(i); return this; } } } class LIB_SlidingWindowAggregation<T> { T[][] list; T[][] agg; int[] size; Func<T, T, T> fun; [MethodImpl(MethodImplOptions.AggressiveInlining)] public LIB_SlidingWindowAggregation(IEnumerable<T> ary, Func<T, T, T> f) { list = new T[2][]; agg = new T[2][]; size = new int[2]; fun = f; list[0] = new T[16]; agg[0] = new T[16]; size[0] = 0; if (ary.Any()) { var temp = ary.ToArray(); size[1] = temp.Length; list[1] = new T[size[1]]; agg[1] = new T[size[1]]; for (var i = 0; i < list[1].Length; i++) { list[1][i] = temp[i]; if (i == 0) agg[1][i] = temp[i]; else agg[1][i] = fun(agg[1][i - 1], temp[i]); } } else { list[1] = new T[16]; agg[1] = new T[16]; size[1] = 0; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public LIB_SlidingWindowAggregation(Func<T, T, T> f) : this(new T[0], f) { } public int Count => size[0] + size[1]; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Clear() { size[0] = size[1] = 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] void Push(int lista, T val) { if (list[lista].Length == size[lista]) { var newAry = new T[size[lista] * 2]; var newAgg = new T[size[lista] * 2]; Array.Copy(list[lista], newAry, size[lista]); Array.Copy(agg[lista], newAgg, size[lista]); list[lista] = newAry; agg[lista] = newAgg; } if (size[lista] == 0) agg[lista][0] = val; else if (lista == 0) agg[lista][size[lista]] = fun(val, agg[lista][size[lista] - 1]); else agg[lista][size[lista]] = fun(agg[lista][size[lista] - 1], val); list[lista][size[lista]++] = val; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PushBack(T val) => Push(1, val); [MethodImpl(MethodImplOptions.AggressiveInlining)] public void PushFront(T val) => Push(0, val); [MethodImpl(MethodImplOptions.AggressiveInlining)] T Pop(int lista) { var listb = 1 - lista; if (size[lista] == 0) { if (size[listb] == 0) throw new Exception(); var mid = (size[listb] - 1) / 2; if (list[lista].Length <= mid) { list[lista] = new T[mid + 1]; agg[lista] = new T[mid + 1]; } size[lista] = 0; for (var i = mid; i >= 0; i--) { if (size[lista] == 0) agg[lista][size[lista]] = list[listb][i]; else if (lista == 0) agg[lista][size[lista]] = fun(list[listb][i], agg[lista][size[lista] - 1]); else agg[lista][size[lista]] = fun(agg[lista][size[lista] - 1], list[listb][i]); list[lista][size[lista]++] = list[listb][i]; } for (var i = mid + 1; i < size[listb]; i++) { var idx = i - mid - 1; if (idx == 0) agg[listb][idx] = list[listb][i]; else if (lista == 0) agg[listb][idx] = fun(list[listb][i], agg[listb][idx - 1]); else agg[listb][idx] = fun(agg[listb][idx - 1], list[listb][i]); list[listb][idx] = list[listb][i]; } size[listb] -= size[lista]; } return list[lista][--size[lista]]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public T PopBack() => Pop(1); [MethodImpl(MethodImplOptions.AggressiveInlining)] public T PopFront() => Pop(0); [MethodImpl(MethodImplOptions.AggressiveInlining)] public T Aggregate() { if (size[0] == 0 && size[1] == 0) throw new Exception(); else if (size[1] == 0) return agg[0][size[0] - 1]; else if (size[0] == 0) return agg[1][size[1] - 1]; else return fun(agg[0][size[0] - 1], agg[1][size[1] - 1]); } } }