結果

問題 No.3078 Difference Sum Query
コンテスト
ユーザー 👑 b1agmpo1e
提出日時 2026-02-07 01:25:15
言語 C#
(.NET 10.0.101)
結果
AC  
実行時間 1,530 ms / 2,000 ms
コード長 38,344 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 20,003 ms
コンパイル使用メモリ 173,356 KB
実行使用メモリ 149,084 KB
最終ジャッジ日時 2026-02-07 01:26:16
合計ジャッジ時間 52,050 ms
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2
other AC * 26
権限があれば一括ダウンロードができます
コンパイルメッセージ
  復元対象のプロジェクトを決定しています...
  /home/judge/data/code/main.csproj を復元しました (134 ミリ秒)。
/home/judge/data/code/Main.cs(553,20): warning CS8981: 型名 'mod' には、小文字の ASCII 文字のみが含まれています。このような名前は、プログラミング言語用に予約されている可能性があります。 [/home/judge/data/code/main.csproj]
/home/judge/data/code/Main.cs(576,20): warning CS8981: 型名 'toolbox' には、小文字の ASCII 文字のみが含まれています。このような名前は、プログラミング言語用に予約されている可能性があります。 [/home/judge/data/code/main.csproj]
/home/judge/data/code/Main.cs(486,20): warning CS8981: 型名 'input' には、小文字の ASCII 文字のみが含まれています。このような名前は、プログラミング言語用に予約されている可能性があります。 [/home/judge/data/code/main.csproj]
/home/judge/data/code/Main.cs(93,29): warning CS8981: 型名 'node' には、小文字の ASCII 文字のみが含まれています。このような名前は、プログラミング言語用に予約されている可能性があります。 [/home/judge/data/code/main.csproj]
  main -> /home/judge/data/code/bin/Release/net10.0/main.dll
  main -> /home/judge/data/code/bin/Release/net10.0/publish/

ソースコード

diff #
raw source code

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Xml.Schema;

namespace test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            cin = new input();
            mod = new mod(998244353);
            toolbox = new toolbox();
            Priority_Queue = new Priority_Queue(true);
            var sw = new System.IO.StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            Console.SetOut(sw);
            toolbox.StartTimer();

            int n=cin.intreed();
            int q=cin.intreed();
            var a=cin.arraylong(n);
            var wm=new ThisIsNotAWavelet_Matrix(a);

            while(q-->0)
            {
                int l=cin.intreed();
                int r=cin.intreed()+1;
                long x=cin.longreed();
                var cnt=wm.CountLower(l,r,x);
                var ans=(x*cnt)-wm.SumLower(l,r,x)-(r-l-cnt)*x+wm.RangeSum(l,r,x,long.MaxValue);
                System.Console.WriteLine(ans);
            }

            toolbox.PrintElapsedTime();
            Console.Out.Flush();
        }
        static input cin;
        static mod mod;
        static toolbox toolbox;
        static Priority_Queue Priority_Queue;
    }

    public class ThisIsNotAWavelet_Matrix
    {
        //1index!!
        //クエリの失敗は-1

        public class Compress<T2>
            where T2 : struct, IComparable
        {
            //1indexだよ!!!! 例[1,5,8,9,5,5]=>[1,2,3,4,2,2]
            public Dictionary<int, T2> key2raw;
            public Dictionary<T2, int> raw2key;
            //やりたいこと 構築 生=>圧縮後 圧縮後=>生
            public Compress(IEnumerable<T2> vector = null)
            {
                key2raw = new Dictionary<int, T2>();
                raw2key = new Dictionary<T2, int>();
                if (vector is { })
                    Build(vector);
            }

            public (List<int>, IOrderedEnumerable<T2>) Build(IEnumerable<T2> vector)
            {
                int cnt = 0;
                var back = new List<int>();
                var sorted = vector.OrderBy(i => i);
                foreach (var i in sorted)
                {
                    if (!raw2key.ContainsKey(i))
                    {
                        cnt++;
                        raw2key.Add(i, cnt);
                        key2raw.Add(cnt, i);
                    }
                }
                foreach (var i in vector)
                    back.Add(raw2key[i]);
                return (back, sorted);
            }

            //インデクサは圧縮後=>生
            public T2 this[int k] => key2raw[k];
            public int Count => key2raw.Count;
        }

        //treeのnodesizeは要素数に応じて決定 1e5なら3*1e6,2*1e5なら5*1e6 5*1e5なら2*1e7
        public class SegmentTree
        {
            //たまには1indexで書いてみたくないですか? 書きたい
            //とりあえずrange sum
            internal struct node
            {
                //index=0のnodeはnullを表す
                public int cnt;//この値の数
                public long sum;//cnt*(圧縮前のこの値)
                public int left;
                public int right;
                public node(int a) => cnt = a;
                public node()
                {
                    cnt = 0;
                    left = 0;
                    right = 0;
                    sum = 0;
                }
            }

            public List<int> roots;//roots[i]=>バージョンiのrootのインデックス root[0]は0が入っている
            internal node[] nodes;
            internal int size;

            public int now_index;
            //5*1e5回のsetをすると、nodesizeは2*1e7でギリギリ(400MB程度) 5*1e7でも速度的には大丈夫だけど、メモリがやばい(900MBギリ下回るぐらい) 
            public SegmentTree(int n, int nodesize = 2 * (int)1e7)
            {
                size = 1;
                while (size < n) size <<= 1;
                nodes = Enumerable.Repeat(new node(), nodesize).ToArray();
                now_index = 2;
                roots = [0, 1];
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="cnt">加算する値</param>
            /// <param name="index">加算する位置(1index)</param>
            /// <param name="real_val">そのノードが担当する圧縮間の、真の値</param>
            /// <param name="version"></param>
            /// <returns></returns>
            public int add(int cnt, int index, long real_val, int version = 1)
            {
                int root = add(cnt, index, roots[version], real_val, 1, size + 1);
                if (root == -1) return -1;
                roots.Add(root);
                return roots.Count - 1;
            }
            /// <summary>
            /// 
            /// </summary>
            /// <param name="cnt">加算する値</param>
            /// <param name="index">加算する位置(1index)</param>
            /// <param name="node_index">現在のノード</param>
            /// <param name="real_val">そのノードが担当する圧縮間の、真の値</param>
            /// <param name="l">現在のノードが担当する範囲の左側(閉区間)</param>
            /// <param name="r">右側(開区間)</param>
            /// <returns>更新後の木のversion</returns>
            private int add(int cnt, int index, int node_index, long real_val, int l, int r)
            {
                if (index < l || r <= index) return -1;
                int now = newnode();
                nodes[now] = nodes[node_index];
                if (l + 1 == r)
                {
                    nodes[now].cnt += cnt;
                    nodes[now].sum = real_val * nodes[now].cnt;
                    return now;
                }
                int mid = (l + r) >> 1;
                if (index < mid)
                {
                    int left = add(cnt, index, nodes[node_index].left, real_val, l, mid);
                    if (left == -1) return -1;
                    nodes[now].left = left;
                }
                else
                {
                    int right = add(cnt, index, nodes[node_index].right, real_val, mid, r);
                    if (right == -1) return -1;
                    nodes[now].right = right;
                }
                nodes[now].cnt = nodes[nodes[now].left].cnt + nodes[nodes[now].right].cnt;
                nodes[now].sum = nodes[nodes[now].left].sum + nodes[nodes[now].right].sum;
                return now;
            }
            /// <summary>
            /// [a,b)のsumのsum
            /// </summary>
            /// <param name="l"></param>
            /// <param name="r"></param>
            /// <param name="version"></param>
            /// <returns></returns>
            public long sum(int l, int r, int version = 1) => sum(l, r, roots[version], 1, size + 1);
            private long sum(int a, int b, int node_index, int l, int r)
            {
                if (node_index == 0) return 0;//nullノード
                if (b <= l || r <= a) return 0;//範囲外
                if (a <= l && r <= b) return nodes[node_index].sum;//完全被覆
                int mid = (l + r) >> 1;
                long left = sum(a, b, nodes[node_index].left, l, mid);
                long right = sum(a, b, nodes[node_index].right, mid, r);
                return left + right;
            }
            /// <summary>
            /// [l,r) 個数について
            /// </summary>
            /// <param name="l"></param>
            /// <param name="r"></param>
            /// <param name="version"></param>
            /// <returns></returns>
            public int query(int l, int r, int version = 1) => query(l, r, roots[version], 1, size + 1);

            private int query(int a, int b, int node_index, int l, int r)
            {
                if (node_index == 0) return 0;//nullノード
                if (b <= l || r <= a) return 0;//範囲外
                if (a <= l && r <= b) return nodes[node_index].cnt;//完全被覆
                int mid = (l + r) >> 1;
                int left = query(a, b, nodes[node_index].left, l, mid);
                int right = query(a, b, nodes[node_index].right, mid, r);
                return left + right;
            }
            /// <summary>
            /// 1index 単独の個数について
            /// </summary>
            /// <param name="index"></param>
            /// <param name="version"></param>
            /// <returns></returns>
            public int get(int index, int version = 1)
            {
                int l = 1;
                int r = size + 1;
                int now = roots[version];
                while (true)
                {
                    if (now == 0)
                        return 0;//nullノード
                    if (index < l || r <= index) return 0;
                    if (l + 1 == r)
                        return nodes[now].cnt;
                    int mid = (l + r) >> 1;
                    if (index < mid)
                    {
                        now = nodes[now].left;
                        r = mid;
                    }
                    else
                    {
                        now = nodes[now].right;
                        l = mid;
                    }
                }
            }

            private int newnode() => now_index++;

        }
        public SegmentTree tree;
        public Compress<long> comp;
        public List<long> rows;//重複を排除した座標圧縮前の配列の要素全て(ソート済み)
        private const int NodePoolMargin = 100;
        public ThisIsNotAWavelet_Matrix(IEnumerable<long> arr)
        {
            //座標圧縮してから構築する
            comp = new Compress<long>();
            var comped = comp.Build(arr);
            var arr_list = arr.ToList();
            int nodesize = GetNodePoolSize();
            tree = new SegmentTree(comp.Count + 1, nodesize);
            int version = 1;
            for (int i = 0; i < arr_list.Count; i++)
            {
                version = tree.add(1, comped.Item1[i], arr_list[i], version);
            }
            rows = comped.Item2.Distinct().ToList();
            int GetNodePoolSize()
            {
                int n = comped.Item1.Count;
                int k = comp.Count+1;
                int size = 1;
                int height = 0;
                while (size < k)
                {
                    size <<= 1;
                    height++;
                }
                height++;
                return 2 + n * height + NodePoolMargin;//2(nullと初期ノード)+n*(add1回で作らないといけないノード数<=>木の高さ)+マージン
            }
        }
        //区間[a,b)でk番目に大きい値を取得する
        public long GetKthLargest(int a, int b, int k)
        {
            //root[b]とroot[a]を見比べればいい varsion=1は全て0の状態 version=2がarrの最初の要素を入れた状態であることに注意せよ つまり、versionは1ずれている
            if (a < 1 || b < 1 || a >= b) return -1;//区間が不正
            if (b > tree.roots.Count - 1) return -1;//範囲外
            long total = tree.nodes[tree.roots[b]].cnt - tree.nodes[tree.roots[a]].cnt;
            if (k <= 0 || total < k) return -1;//そんな要素ないです

            //今見てるノード
            int node_a = tree.roots[a];
            int node_b = tree.roots[b];
            //今見てる区間
            int l = 1;
            int r = tree.size + 1;

            while (l + 1 != r)
            {
                int left_a = tree.nodes[node_a].left;
                int left_b = tree.nodes[node_b].left;
                int right_a = tree.nodes[node_a].right;
                int right_b = tree.nodes[node_b].right;
                int cnt_right = tree.nodes[right_b].cnt - tree.nodes[right_a].cnt;//この区間の右側にある要素数
                int mid = (l + r) >> 1;

                if (cnt_right >= k)
                {
                    node_a = right_a;
                    node_b = right_b;
                    l = mid;
                }
                else
                {
                    k -= cnt_right;
                    node_a = left_a;
                    node_b = left_b;
                    r = mid;
                }
            }
            return comp[l];
        }
        //区間[a,b)でk番目に小さい値を返す
        public long GetKthSmallest(int a, int b, int k)
        {
            if (a < 1 || b < 1 || a >= b) return -1;//区間が不正
            if (b > tree.roots.Count - 1) return -1;//範囲外
            int total = tree.nodes[tree.roots[b]].cnt - tree.nodes[tree.roots[a]].cnt;
            if (k <= 0 || total < k) return -1;//そんな要素ないです
            return GetKthLargest(a, b, total - k + 1);//k番目に大きい値に変更して投げる
        }
        //区間[a,b)の要素で[x,y)を満たすものの要素を数える a,b,x,yのどれかが不正だと壊れるよ
        public int RangeFreq(int a, int b, long x, long y) => CountLower(a, b, y) - CountLower(a, b, x);
        //区間[a,b)の要素でx未満の要素の数を数える
        public int CountLower(int a, int b, long x)
        {
            if (a < 1 || b < 1 || a >= b) return -1;//区間が不正
            if (b > tree.roots.Count - 1) return -1;//範囲外
            int x_comped = rows.BinarySearch(x);
            if (x_comped < 0) x_comped = ~x_comped;
            x_comped++;
            int l = tree.query(1, x_comped, a);//[1,a)でのクエリ結果
            var r = tree.query(1, x_comped, b);//[1,b)でのクエリ結果
            //xを圧縮後の世界に飛ばす x未満を数えるから、xを超える最小値を探してきて、それでいい

            return r - l;//[1,b)-[1,a)=[a,b)
        }
        //区間[a,b)でx未満の最大値を返す
        public long PrevValue(int a, int b, long x)
        {
            //サボり実装
            int cnt = CountLower(a, b, x);//区間[a,b)でx未満の個数を数える
            if (cnt <= 0) return -1;
            return GetKthSmallest(a, b, cnt);//求める値はcnt番目に小さいもの
        }
        //区間[a,b)でx以上の最小値を返す
        public long NextValue(int a, int b, long x)
        {
            int cnt = CountLower(a, b, x);//区間[a,b)でx未満の個数を数える
            if (cnt < 0) return -1;
            return GetKthSmallest(a, b, cnt + 1);//cnt+1はx以上になる最初の値の順位
        }
        //区間[1,b)でxが登場する回数を返す
        public int Count(int b, long x)
        {
            var index = rows.BinarySearch(x);
            if (index < 0)
                return 0;//xは1度も登場しない
            index++;
            return tree.get(index, b);
        }
        //区間[a,b)でxが登場する回数を返す
        public int Count(int a, int b, long x) => Count(b, x) - Count(a, x);
        //区間[a,b)で要素xがi回目に登場するインデックスを返す 計算量O(logN*log(種類数))
        public int Select(int a, int b, long x, int cnt)
        {
            //xは座標圧縮後であることに注意せよ
            int Count(int a, int b, int x) => tree.get(x, b) - tree.get(x, a);

            if (a < 1 || b < 1 || a >= b) return -1;//区間が不正
            if (b > tree.roots.Count - 1) return -1;//範囲外
            if (cnt <= 0) return -1;
            var index = rows.BinarySearch(x);
            if (index < 0) return -1;//そんな要素存在しない
            index++;
            int total = Count(a, b, index);
            if (total < cnt) return -1;

            int l = a;
            int r = b;
            while (l + 1 < r)
            {
                int mid = (l + r) >> 1;
                int left = Count(l, mid, index);
                if (left >= cnt)
                {
                    r = mid;
                }
                else
                {
                    l = mid;
                    cnt -= left;
                }
            }
            return l;
        }
        //区間[a,b)でx未満の要素のsumを返す
        public long SumLower(int a, int b, long x)
        {
            //負の値が入っていても壊れないように、クエリ失敗は-INFとする
            if (a < 1 || b < 1 || a >= b) return long.MinValue;//区間が不正
            if (b > tree.roots.Count - 1) return long.MinValue;//範囲外
            int x_comped = rows.BinarySearch(x);
            if (x_comped < 0) x_comped = ~x_comped;
            x_comped++;
            long l = tree.sum(1, x_comped, a);//[1,a)
            long r = tree.sum(1, x_comped, b);//[1,b)
            return r - l;//[1,b)-[1,a)=[a,b)
        }
        //区間[a,b)の要素で[x,y)を満たすもののsumを返す
        public long RangeSum(int a, int b, long x, long y)
        {
            long r = SumLower(a, b, y);
            long l = SumLower(a, b, x);
            if (r is long.MinValue || l is long.MinValue)
                return -1;
            return r - l;
        }
    }
    public static class Extensions
    {
        public static Dictionary<T, int> safe_addtion_for_dictionary_int<T>(this Dictionary<T, int> dic, T key)
        {
            if (dic.ContainsKey(key))
                dic[key]++;
            else
                dic.Add(key, 1);
            return dic;
        }

        public static Dictionary<T, long> safe_addtion_for_dictionary_long<T>(this Dictionary<T, long> dic, T key)
        {
            if (dic.ContainsKey(key))
                dic[key]++;
            else
                dic.Add(key, 1);
            return dic;
        }

        public static Dictionary<T, List<T2>> safe_addtion_for_list_in_dictionary<T, T2>(this Dictionary<T, List<T2>> dic, T key, T2 value)
        {
            if (dic.ContainsKey(key))
                dic[key].Add(value);
            else
                dic.Add(key, new List<T2>() { value });
            return dic;
        }

        public static T list_pop_back<T>(this List<T> a)
        {
            var k = a[a.Count - 1];
            a.RemoveAt(a.Count - 1);
            return k;
        }

        public static T chmin<T>(ref this T a, T b)
            where T : struct, IComparable
        {
            if (a.CompareTo(b) > 0)
                return a = b;
            else
                return a;
        }
        public static T chmax<T>(ref this T a, T b)
            where T : struct, IComparable
        {
            if (a.CompareTo(b) < 0)
                return a = b;
            else
                return a;
        }

    }

    internal class input
    {
        string[] soloinput;
        int t;
        public input()
        {
            soloinput = new string[0];
            t = 0;
        }
        public string soloreed()
        {
            if (t < soloinput.Length)
            {
                return soloinput[t++];
            }
            string input = Console.ReadLine();
            while (input == "")
            {
                input = Console.ReadLine();
            }
            soloinput = input.Split(" ");
            t = 0;
            return soloinput[t++];
        }
        public int intreed()
        {
            return int.Parse(soloreed());
        }
        public int[] arrayint(int N)
        {
            int[] A = new int[N];
            for (int i = 0; i < N; i++)
            {
                A[i] = intreed();
            }
            return A;
        }
        public long longreed()
        {
            return long.Parse(soloreed());
        }
        public long[] arraylong(long N)
        {
            long[] A = new long[N];
            for (long i = 0; i < N; i++)
            {
                A[i] = longreed();
            }
            return A;
        }
        public decimal decimalreed()
        {
            return decimal.Parse(soloreed());
        }
        public decimal[] arraydecimal(long N)
        {
            decimal[] A = new decimal[N];
            for (decimal i = 0; i < N; i++)
            {
                A[(long)i] = decimalreed();
            }
            return A;
        }


    }

    internal class mod
    {
        public long T { get; set; }
        public mod(long mod = 1000000007)
        {
            T = mod;
        }
        public long addition(long A, long B)
        {
            long C = A + B;
            return (long)C % T;
        }
        public long subtraction(long A, long B)
        {
            return ((A % T) - (B % T) + T) % T;
        }
        public long multiplication(long A, long B)
        {
            return ((A % T) * (B % T)) % T;
        }

    }

    internal class toolbox
    {

        string Y = "Yes";
        string N = "No";
        static input cin;
        public DateTime? startTime;
        public toolbox()
        {
            cin = new input();
        }

        public long[] CumulativeSum(long[] A, bool mode = true)
        {
            if (mode == false) Array.Reverse(A);
            long[] back = new long[A.Length + 1];
            back[0] = 0;
            for (int i = 1; i <= A.Length; i++)
            {
                back[i] = back[i - 1] + A[i - 1];
            }
            if (mode == false) Array.Reverse(A);
            return back;
        }

        public long[] Eratosthenes(long A)
        {
            A++;
            var back = new List<long>();
            bool[] ch = new bool[A];
            for (int i = 2; i < A; i++) ch[i] = true;
            for (long i = 2; i < Math.Sqrt(A); i++)
            {
                if (ch[i] == true)
                {
                    back.Add(i);
                    for (long t = 1; i * t < A; t++)
                    {
                        ch[i * t] = false;
                    }
                }
            }
            for (long i = 0; i < A; i++)
            {
                if (ch[i] == true) back.Add(i);
            }
            return back.Distinct().ToArray();
        }
        public void Swap<T>(ref T a, ref T b)
        {
            var i = a;
            a = b;
            b = i;
        }

        public void LSwap<T>(ref List<T> A, int a, int b)
        {
            var i = A[a];
            A[a] = A[b];
            A[b] = i;
        }

        public long Gcd(long A, long B)
        {
            while (A != 0)
            {
                B %= A;
                Swap(ref A, ref B);
            }
            return B;
        }

        public long[] AllDivisors(long N)
        {
            var back = new List<long>();
            for (int i = 1; Math.Pow(i, 2) <= N; i++)
            {
                if (N % i == 0)
                {
                    back.Add(i);
                    back.Add(N / i);
                }
            }
            return back.Distinct().ToArray();
        }

        public static IEnumerable<T[]> ExhaustiveEnumeration<T>(IEnumerable<T> indata)
        {
            if (indata.Count() == 1) yield return new T[] { indata.First() };
            foreach (var i in indata)
            {
                var used = new T[] { i };
                var unused = indata.Except(used);
                foreach (var t in ExhaustiveEnumeration(unused))
                    yield return used.Concat(t).ToArray();
            }
            //How to use
            //var allpattern = toolbox.ExhaustiveEnumeration(Enumerable.Range(1, N));
        }

        public bool[,] bitallsearch(int N)
        {
            bool[,] back = new bool[(int)Math.Pow(2, N), N];
            for (int i = 0; i < Math.Pow(2, N); i++)
            {
                for (int t = 0; t < N; t++)
                {
                    var k = (i >> t) & 1;
                    if (k == 1)
                    {
                        back[i, t] = true;
                    }
                }
            }
            return back;
        }

        public static int BS<T>(T[] A, T key)
            where T : IComparable
        {
            //このコード、定数倍が大変な事になってるので標準ライブラリを使いましょう(BinarySearch)
            int left = 0;
            int right = A.Length;
            int mid = 0;
            while (left < right)
            {
                mid = (left + right) / 2;
                if (A[mid].CompareTo(key) == 0)
                    return mid;
                else if (A[mid].CompareTo(key) > 0)
                    right = mid;
                else if (A[mid].CompareTo(key) < 0)
                    left = mid + 1;
            }
            return -1;
        }

        public static int lower_bound<T>(T[] a, T v)
        {
            return lower_bound(a, v, Comparer<T>.Default);
        }

        public static int lower_bound<T>(T[] A, T key, Comparer<T> v)
        {
            int left = 0;
            int right = A.Length - 1;
            int mid = 0;
            var W = 0;
            while (left <= right)
            {
                mid = (left + right) / 2;
                W = v.Compare(A[mid], key);
                if (W == -1)
                    left = mid + 1;
                else
                    right = mid - 1;
            }
            return left;
        }

        public long[] prime_factorize(long N)
        {
            long T = N;
            var back = new List<long>();
            for (long i = 2; i * i <= T; i++)
            {
                if (T % i != 0) continue;
                while (T % i == 0)
                {
                    back.Add(i);
                    T /= i;
                }
            }
            if (T != 1) back.Add(T);
            return back.ToArray();
        }

        public long[] One_dimensional_Coordinate_Compression(long[] A)
        {
            long[] back = new long[A.Length];
            var T = A.Distinct().ToList();
            T.Sort();
            for (int i = 0; i < A.Length; i++)
                back[i] = T.BinarySearch(A[i]);
            return back;
        }

        public void setYN(string A = "Yes", string B = "No")
        {
            Y = A;
            N = B;
        }

        public void YN(bool ans)
        {
            if (ans)
                Console.WriteLine(Y);
            else
                Console.WriteLine(N);
        }

        public string[] x_dekakou(int H, int W)
        {
            var s = new string[H + 2];
            for (int i = 0; i < W + 2; i++)
            {
                s[0] += "x";
                s[H + 1] += "x";
            }
            for (int i = 1; i < H + 1; i++)
            {
                //x場外 .白 #黒
                s[i] = "x" + Console.ReadLine().Replace(" ", "") + "x";
            }
            return s;
        }

        public List<List<int>> x_dekakou_string(int H, int W)
        {
            var back = new List<List<int>>();
            for (int i = 0; i < H + 2; i++)
                back.Add(Enumerable.Repeat<int>(-1, W + 2).ToList());
            for (int i = 0; i < W + 2; i++)
            {
                back[0][i] = -1;
                back[H + 1][i] = -1;
            }
            for (int i = 1; i <= H; i++)
            {
                back[i][0] = -1;
                back[i][W + 1] = -1;
                for (int t = 1; t <= W; t++)
                    back[i][t] = cin.intreed();
            }
            return back;
        }
        /// <summary>
        /// 配列の指定位置以降を反転する
        /// </summary>
        /// <param name="array">反転対象の配列</param>
        /// <param name="begin">反転開始位置(この位置以降が反転される)</param>
        private void Reverse<T>(T[] array, int begin) where T : IComparable<T>
        {
            // 反転する要素が2個未満の場合は何もしない
            if (array.Length - begin < 2) return;

            // 両端から中央に向かって要素を交換
            int left = begin;
            int right = array.Length - 1;
            while (left < right)
            {
                Swap(ref array[left], ref array[right]);
                left++;
                right--;
            }
        }

        /// <summary>
        /// 配列を辞書順で次の順列に変更する
        /// 全ての順列を列挙するには、事前に Array.Sort() でソートした配列を渡すこと
        /// </summary>
        /// <param name="array">順列を生成する配列(事前ソート必須)</param>
        /// <returns>次の順列が存在する場合true、最大順列の場合false</returns>
        public bool NextPermutation<T>(T[] array) where T : IComparable<T>
        {
            // 辞書順で次に大きい順列を生成

            // 1. 右端から降順でない位置を探す
            int pivotIndex = -1;
            for (int i = array.Length - 2; i >= 0; i--)
            {
                if (array[i].CompareTo(array[i + 1]) < 0) // 昇順ペア発見
                {
                    pivotIndex = i;
                    break;
                }
            }

            // 最大順列に到達している場合
            if (pivotIndex == -1) return false;

            // 2. pivotより大きい最右の要素と交換
            for (int j = array.Length - 1; j > pivotIndex; j--)
            {
                if (array[pivotIndex].CompareTo(array[j]) < 0)
                {
                    Swap(ref array[pivotIndex], ref array[j]);
                    break;
                }
            }

            // 3. pivot以降を昇順に並べ直し
            Reverse(array, pivotIndex + 1);
            return true;

            // how to use
            // do{}while(NextPermutation)
        }

        /// <summary>
        /// 回文判定のコア処理(配列版)
        /// </summary>
        private bool IsPalindromeCore<T>(T[] array, int left, int right) where T : IComparable<T>
        {
            while (left < right)
            {
                if (array[left].CompareTo(array[right]) != 0)
                    return false;
                left++;
                right--;
            }
            return true;
        }

        /// <summary>
        /// 回文判定のコア処理(文字列版)
        /// </summary>
        private bool IsPalindromeCore(string str, int left, int right)
        {
            while (left < right)
            {
                if (str[left] != str[right])
                    return false;
                left++;
                right--;
            }
            return true;
        }

        /// <summary>
        /// 配列全体が回文かどうかを判定
        /// </summary>
        public bool IsPalindrome<T>(T[] array) where T : IComparable<T>
        {
            return IsPalindromeCore(array, 0, array.Length - 1);
        }

        /// <summary>
        /// 文字列全体が回文かどうかを判定
        /// </summary>
        public bool IsPalindrome(string str)
        {
            return IsPalindromeCore(str, 0, str.Length - 1);
        }

        /// <summary>
        /// 指定範囲が回文かどうかを判定(配列版)
        /// </summary>
        public bool IsPalindrome<T>(T[] array, int start, int end) where T : IComparable<T>
        {
            return IsPalindromeCore(array, start, end);
        }

        /// <summary>
        /// 指定範囲が回文かどうかを判定(文字列版)
        /// </summary>
        public bool IsPalindrome(string str, int start, int end)
        {
            return IsPalindromeCore(str, start, end);
        }

        /// <summary>
        /// 指定長さの部分配列に回文が含まれるかを判定
        /// </summary>
        public bool HasPalindrome<T>(T[] array, int length) where T : IComparable<T>
        {
            for (int i = 0; i <= array.Length - length; i++)
            {
                if (IsPalindromeCore(array, i, i + length - 1))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 指定長さの部分文字列に回文が含まれるかを判定
        /// </summary>
        public bool HasPalindrome(string str, int length)
        {
            for (int i = 0; i <= str.Length - length; i++)
            {
                if (IsPalindromeCore(str, i, i + length - 1))
                    return true;
            }
            return false;
        }


        public long modpow(long x, long p, long mod = 1000000007)
        {
            long result = 1;
            x %= mod;
            while (p > 0)
            {
                if (p % 2 == 1)        // pが奇数の場合
                {
                    result = (result * x) % mod;
                }
                x = (x * x) % mod;      // xを二乗(これが繰り返し二乗)
                p /= 2;                 // pを半分にする
            }
            return result;
        }

        public void StartTimer()
        {
            startTime = DateTime.Now;
        }

        public void PrintElapsedTime(bool error_output = true)
        {
            //標準出力ではなくて標準エラー出力を使ってるのでatcoderのジャッジはこの出力を無視する つまり消さなくてok 便利だね
            if (startTime.HasValue)
            {
                var elapsed = DateTime.Now - startTime.Value;
                if (error_output)
                    Console.Error.WriteLine($"Elapsed time: {elapsed.TotalMilliseconds} ms");
                else
                    Console.WriteLine($"Elapsed time: {elapsed.TotalMilliseconds} ms");


            }
            else
            {
                Console.Error.WriteLine("Timer was not started.");
            }
        }
    }

    internal class Priority_Queue
    {
        toolbox toolbox = new toolbox();
        public List<(long, long)> Queue { get; private set; }
        /// <summary>
        /// true==>大きいやつから出るよ false==>小さいやつからでるよ
        /// </summary>
        public bool revase { get; set; }
        public Priority_Queue(bool cnt = true)
        {
            Queue = new List<(long, long)>();
            revase = cnt;
        }

        public void Enqueue(long a, long b)
        {
            if (revase == false)
                a *= -1;
            int i = Queue.Count, t;
            Queue.Add((a, b));
            while (i != 0)
            {
                t = (i - 1) / 2;
                if (Queue[i].Item1 > Queue[t].Item1)
                {
                    var k = Queue[i];
                    Queue[i] = Queue[t];
                    Queue[t] = k;
                    i = t;
                }
                else
                {
                    break;
                }
            }
        }

        public (long, long) Dequeue()
        {
            int a = Queue.Count - 1;
            var back = Queue[0];
            Queue[0] = Queue[a];
            Queue.RemoveAt(a);
            for (int i = 0, j; (j = 2 * i + 1) < a;)
            {
                if (j != a - 1 && Queue[j].Item1 < Queue[j + 1].Item1)
                    j++;
                if (Queue[i].Item1 < Queue[j].Item1)
                {
                    var k = Queue[i];
                    Queue[i] = Queue[j];
                    Queue[j] = k;
                    i = j;
                }
                else
                {
                    break;
                }
            }
            if (revase == false)
                back.Item1 *= -1;
            return back;

        }

        public (long, long) GetPeek() => (revase ? Queue[0].Item1 : Queue[0].Item1 * -1, Queue[0].Item2);
    }

    internal class Generic_Priority_Queue<T>
    {
        toolbox toolbox = new toolbox();
        public List<(long, T)> Queue { get; private set; }
        /// <summary>
        /// true==>大きいやつから出るよ false==>小さいやつからでるよ
        /// </summary>
        public bool revase { get; set; }
        public Generic_Priority_Queue(bool cnt = true)
        {
            Queue = new List<(long, T)>();
            revase = cnt;
        }

        public void Enqueue(long a, T b)
        {
            if (revase == false)
                a *= -1;
            int i = Queue.Count, t;
            Queue.Add((a, b));
            while (i != 0)
            {
                t = (i - 1) / 2;
                if (Queue[i].Item1 > Queue[t].Item1)
                {
                    var k = Queue[i];
                    Queue[i] = Queue[t];
                    Queue[t] = k;
                    i = t;
                }
                else
                {
                    break;
                }
            }
        }

        public (long, T) Dequeue()
        {
            int a = Queue.Count - 1;
            var back = Queue[0];
            Queue[0] = Queue[a];
            Queue.RemoveAt(a);
            for (int i = 0, j; (j = 2 * i + 1) < a;)
            {
                if (j != a - 1 && Queue[j].Item1 < Queue[j + 1].Item1)
                    j++;
                if (Queue[i].Item1 < Queue[j].Item1)
                {
                    var k = Queue[i];
                    Queue[i] = Queue[j];
                    Queue[j] = k;
                    i = j;
                }
                else
                {
                    break;
                }
            }
            if (revase == false)
                back.Item1 *= -1;
            return back;

        }

        public (long, T) get_first()
        {
            if (Queue.Count == 0)
                return (default(long), default(T));
            else
                return Queue[0];
        }
    }

}
0