結果

問題 No.386 貪欲な領主
ユーザー eitahoeitaho
提出日時 2016-07-10 07:21:00
言語 C#(csc)
(csc 3.9.0)
結果
AC  
実行時間 657 ms / 2,000 ms
コード長 5,721 bytes
コンパイル時間 3,739 ms
コンパイル使用メモリ 118,316 KB
実行使用メモリ 76,016 KB
最終ジャッジ日時 2024-04-21 11:13:59
合計ジャッジ時間 9,647 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 30 ms
19,456 KB
testcase_01 AC 31 ms
19,456 KB
testcase_02 AC 33 ms
19,456 KB
testcase_03 AC 34 ms
19,200 KB
testcase_04 AC 657 ms
76,016 KB
testcase_05 AC 574 ms
50,284 KB
testcase_06 AC 569 ms
50,176 KB
testcase_07 AC 36 ms
20,736 KB
testcase_08 AC 104 ms
26,368 KB
testcase_09 AC 41 ms
21,248 KB
testcase_10 AC 34 ms
19,328 KB
testcase_11 AC 31 ms
19,200 KB
testcase_12 AC 34 ms
20,352 KB
testcase_13 AC 48 ms
22,232 KB
testcase_14 AC 582 ms
50,032 KB
testcase_15 AC 518 ms
73,584 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
Microsoft (R) Visual C# Compiler version 3.9.0-6.21124.20 (db94f4cc)
Copyright (C) Microsoft Corporation. All rights reserved.

ソースコード

diff #

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics;
using Enu = System.Linq.Enumerable;

public class Program
{
    List<int>[] E;
    int[] C;
    int[] S;

    public void Solve()
    {
        int N = Reader.Int();
        E = Enu.Range(0, N).Select(i => new List<int>()).ToArray();
        for (int i = 0; i < N - 1; i++)
        {
            int a = Reader.Int(), b = Reader.Int();
            E[a].Add(b);
            E[b].Add(a);
        }
        C = Reader.IntArray(N);
        int Q = Reader.Int();
        var table = Reader.IntTable(Q);
        S = new int[N];
        DFS(0, -1, 0);
        var LCA = new LowestCommonAncestor(0, E);
        long ans = 0;

        foreach (var q in table)
        {
            int lca = LCA.Get(q[0], q[1]);
            ans += q[2] * (S[q[0]] + S[q[1]] - S[lca] * 2 + C[lca]);
        }

        Console.WriteLine(ans);
    }

    void DFS(int v, int prev, int sumCost)
    {
        sumCost += C[v];
        S[v] += sumCost;
        foreach (int next in E[v])
            if (next != prev)
                DFS(next, v, sumCost);
    }


    class LowestCommonAncestor
    {
        List<int>[] G;
        RangeMinQueryIndex Rmq;
        List<int> Vs = new List<int>();
        List<int> Depth = new List<int>();
        int[] Id;

        public LowestCommonAncestor(int root, List<int>[] G)
        {
            this.G = G;
            Init(root);
        }
        public int Get(int a, int b)
        {
            int L = Math.Min(Id[a], Id[b]);
            int R = Math.Max(Id[a], Id[b]) + 1;
            int i = Rmq.Get(L, R);
            return Vs[i];
        }
        private void Init(int root)
        {
            Id = new int[G.Length];
            DFS(root, -1, 0);
            Rmq = new RangeMinQueryIndex(Depth.Count);
            for (int i = 0; i < Depth.Count; i++)
                Rmq.Set(i, Depth[i]);
        }
        private void DFS(int v, int prev, int d)
        {
            Id[v] = Vs.Count;
            Vs.Add(v);
            Depth.Add(d);
            foreach (int next in G[v])
                if (next != prev)
                {
                    DFS(next, v, d + 1);
                    Vs.Add(v);
                    Depth.Add(d);
                }
        }
    }

    class RangeMinQueryIndex
    {
        private static readonly int INF = (int)1e9;
        public readonly int N;
        private readonly int[] tree;
        private readonly int[] index;

        public RangeMinQueryIndex(int N)
        {
            while (N < 2 || (N & (N - 1)) != 0) { N += N & -N; }
            this.N = N;
            tree = new int[N * 2];
            index = new int[N * 2];
            for (int i = 0; i < tree.Length; i++) tree[i] = INF;
        }
        public void Set(int i, int val)
        {
            int id = i;
            i += N - 1;
            tree[i] = val;
            index[i] = id;
            while (i > 0)
            {
                i = (i - 1) / 2;
                int L = i * 2 + 1, R = i * 2 + 2;
                if (tree[L] <= tree[R]) { tree[i] = tree[L]; index[i] = index[L]; }
                else { tree[i] = tree[R]; index[i] = index[R]; }
            }
        }
        // [L, R)
        public int Get(int L, int R) { int v = -1; return Rec(0, ref v, 0, N, L, R); }
        private int Rec(int i, ref int val, int currL, int currR, int L, int R)
        {
            if (currL >= R || currR <= L) { val = INF; return -1; }
            if (currL >= L && currR <= R) { val = tree[i]; return index[i]; }
            int mid = (currL + currR) / 2;
            int Lv = INF, Rv = INF;
            int Li = Rec(i * 2 + 1, ref Lv, currL, mid, L, R);
            int Ri = Rec(i * 2 + 2, ref Rv, mid, currR, L, R);
            if (Lv <= Rv) { val = Lv; return Li; }
            val = Rv; return Ri;
        }
    }
}


class Entry { static void Main() { new Program().Solve(); } }
class Reader
{
    static TextReader reader = Console.In;
    static readonly char[] separator = { ' ' };
    static readonly StringSplitOptions op = StringSplitOptions.RemoveEmptyEntries;
    static string[] A = new string[0];
    static int i;
    static void Init() { A = new string[0]; }
    public static void Set(TextReader r) { reader = r; Init(); }
    public static void Set(string file) { reader = new StreamReader(file); Init(); }
    public static bool HasNext() { return CheckNext(); }
    public static string String() { return Next(); }
    public static int Int() { return int.Parse(Next()); }
    public static long Long() { return long.Parse(Next()); }
    public static double Double() { return double.Parse(Next()); }
    public static int[] IntLine() { return Array.ConvertAll(Split(Line()), int.Parse); }
    public static int[] IntArray(int N) { return Range(N, Int); }
    public static int[][] IntTable(int H) { return Range(H, IntLine); }
    public static string[] StringArray(int N) { return Range(N, Next); }
    public static string[][] StringTable(int N) { return Range(N, () => Split(Line())); }
    public static string Line() { return reader.ReadLine().Trim(); }
    static T[] Range<T>(int N, Func<T> f) { return Enu.Range(0, N).Select(i => f()).ToArray(); }
    static string[] Split(string s) { return s.Split(separator, op); }
    static string Next() { CheckNext(); return A[i++]; }
    static bool CheckNext()
    {
        if (i < A.Length) return true;
        string line = reader.ReadLine();
        if (line == null) return false;
        if (line == "") return CheckNext();
        A = Split(line);
        i = 0;
        return true;
    }
}
0