Problem:
Score : 100 points

Problem Statement

You are given a grid of N rows and M columns. The square at the i-th row and j-th column will be denoted as (i,j).
Some of the squares contain an object. All the remaining squares are empty.
The state of the grid is represented by strings S_1,S_2,\cdots,S_N. The square (i,j) contains an object if S_{i,j}= # and is empty if S_{i,j}= ..

Consider placing 1 \times 2 tiles on the grid. Tiles can be placed vertically or horizontally to cover two adjacent empty squares.
Tiles must not stick out of the grid, and no two different tiles may intersect. Tiles cannot occupy the square with an object.

Calculate the maximum number of tiles that can be placed and any configulation that acheives the maximum.

Constraints

1 \leq N \leq 100

1 \leq M \leq 100

S_i is a string with length M consists of # and ..

Input

Input is given from Standard Input in the following format:

N M
S_1
S_2
\vdots
S_N

Output

On the first line, print the maximum number of tiles that can be placed.

On the next N lines, print a configulation that achieves the maximum.
Precisely, output the strings t_1,t_2,\cdots,t_N constructed by the following way.

t_i is initialized to S_i.

For each (i,j), if there is a tile that occupies (i,j) and (i+1,j), change t_{i,j}:=v, t_{i+1,j}:=^.

For each (i,j), if there is a tile that occupies (i,j) and (i,j+1), change t_{i,j}:=>, t_{i,j+1}:=<.

See samples for further information.

You may print any configulation that maximizes the number of tiles.

Sample Input 1

3 3
#..
..#
...

Sample Output 1

3
#><
vv#
^^.

The following output is also treated as a correct answer.

3
#><
v.#
^><

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using AtCoderLibraryPracticeContest.Extensions;
using AtCoderLibraryPracticeContest.Questions;
using System.Diagnostics;
using AtCoder;
using AtCoder.Internal;
using System.Runtime.Intrinsics.X86;
using System.Numerics;

namespace AtCoderLibraryPracticeContest.Questions
{
    public class QuestionD : AtCoderQuestionBase
    {
        public override IEnumerable<object> Solve(TextReader inputStream)
        {
            var (height, width) = inputStream.ReadValue<int, int>();
            var n = height * width;
            var map = new char[height][];

            var diffs = new (int dr, int dc)[] { (0, -1), (0, 1), (-1, 0), (1, 0) };

            for (int row = 0; row < height; row++)
            {
                map[row] = inputStream.ReadLine().ToCharArray();
            }

            var graph = new MFGraphInt(n + 2);

            for (int row = 0; row < height; row++)
            {
                for (int column = 0; column < width; column++)
                {
                    var from = GetIndex(row, column);

                    if (((row + column) & 1) == 0 && map[row][column] != '#')
                    {
                        foreach (var (dr, dc) in diffs)
                        {
                            var nextRow = row + dr;
                            var nextColumn = column + dc;

                            if (unchecked((uint)nextRow < height && (uint)nextColumn < width) && map[nextRow][nextColumn] != '#')
                            {
                                var to = GetIndex(nextRow, nextColumn);
                                graph.AddEdge(from, to, 1);
                            }
                        }
                    }
                }
            }

            for (int i = 0; i < n; i++)
            {
                var (row, column) = GetRowColumn(i);
                if (((row + column) & 1) == 0)
                {
                    graph.AddEdge(n, i, 1);
                }
                else
                {
                    graph.AddEdge(i, n + 1, 1);
                }
            }

            var matches = graph.Flow(n, n + 1);

            foreach (var edge in graph.Edges())
            {
                if (edge.Flow == 1 && edge.From < n && edge.To < n)
                {
                    var from = edge.From;
                    var to = edge.To;

                    if (from > to)
                    {
                        (from, to) = (to, from);
                    }

                    var (fromRow, fromColumn) = GetRowColumn(from);
                    var (toRow, toColumn) = GetRowColumn(to);

                    if (fromRow == toRow)
                    {
                        map[fromRow][fromColumn] = '>';
                        map[toRow][toColumn] = '<';
                    }
                    else
                    {
                        map[fromRow][fromColumn] = 'v';
                        map[toRow][toColumn] = '^';
                    }
                }
            }

            yield return matches;

            for (int row = 0; row < map.Length; row++)
            {
                yield return map[row].Join();
            }

            int GetIndex(int row, int column) => row * width + column;
            (int r, int c) GetRowColumn(int index) => (index / width, index % width);
        }


        /// <summary>
        /// 最大フロー問題 を解くライブラリ(int版)です。
        /// </summary>
        public class MFGraphInt : MFGraph<int, IntOperator> { public MFGraphInt(int n) : base(n) { } }

        /// <summary>
        /// 最大フロー問題 を解くライブラリ(long版)です。
        /// </summary>
        public class MFGraphLong : MFGraph<long, LongOperator> { public MFGraphLong(int n) : base(n) { } }

        /// <summary>
        /// 最大フロー問題 を解くライブラリです。
        /// </summary>
        /// <typeparam name="TValue">容量の型</typeparam>
        /// <typeparam name="TOp"><typeparamref name="TValue"/>に対応する演算を提要する型</typeparam>
        /// <remarks>
        /// <para>制約: <typeparamref name="TValue"/> は int, long。</para>
        /// <para>
        /// 内部では各辺 e について 2 つの変数、流量 f_e と容量 c_e を管理しています。
        /// 頂点 v から出る辺の集合を out(v)、入る辺の集合を in(v)、
        /// また頂点 v について g(v, f) = (Σ_in(v) f_e) - (Σ_out(v) f_e) とします。 
        /// </para>
        /// </remarks>
        public class MFGraph<TValue, TOp>
             where TValue : struct
             where TOp : struct, INumOperator<TValue>
        {
            static readonly TOp op = default;

            /// <summary>
            /// <paramref name="n"/> 頂点 0 辺のグラフを作ります。
            /// </summary>
            /// <remarks>
            /// <para>制約: 0 ≤ <paramref name="n"/> ≤ 10^8</para>
            /// <para>計算量: O(<paramref name="n"/>)</para>
            /// </remarks>
            public MFGraph(int n)
            {
                _n = n;
                _g = new List<EdgeInternal>[n];
                for (int i = 0; i < n; i++)
                {
                    _g[i] = new List<EdgeInternal>();
                }
                _pos = new List<(int first, int second)>();
            }

            /// <summary>
            /// <paramref name="from"/> から <paramref name="to"/> へ
            /// 最大容量 <paramref name="cap"/>、流量 0 の辺を追加し、何番目に追加された辺かを返します。
            /// </summary>
            /// <remarks>
            /// 制約: 
            /// <list type="bullet">
            /// <item>
            /// <description>0 ≤ <paramref name="from"/>, <paramref name="to"/> &lt; n</description>
            /// </item>
            /// <item>
            /// <description>0 ≤ <paramref name="cap"/></description>
            /// </item>
            /// </list>
            /// <para>計算量: ならしO(1)</para>
            /// </remarks>
            public int AddEdge(int from, int to, TValue cap)
            {
                int m = _pos.Count;
                Debug.Assert(0 <= from && from < _n);
                Debug.Assert(0 <= to && to < _n);
                Debug.Assert(op.LessThanOrEqual(default, cap));
                _pos.Add((from, _g[from].Count));
                _g[from].Add(new EdgeInternal(to, _g[to].Count, cap));
                _g[to].Add(new EdgeInternal(from, _g[from].Count - 1, default));
                return m;
            }

            /// <summary>
            /// 今の内部の辺の状態を返します。
            /// </summary>
            /// <remarks>
            /// <para>AddEdge で <paramref name="i"/> 番目 (0-indexed) に追加された辺を返す。</para>
            /// <para>計算量: O(1)</para>
            /// </remarks>
            public Edge GetEdge(int i)
            {
                int m = _pos.Count;
                Debug.Assert(0 <= i && i < m);
                var _e = _g[_pos[i].first][_pos[i].second];
                var _re = _g[_e.To][_e.Rev];
                return new Edge(_pos[i].first, _e.To, op.Add(_e.Cap, _re.Cap), _re.Cap);
            }

            /// <summary>
            /// 今の内部の辺の状態を返します。
            /// </summary>
            /// <remarks>
            /// <para>辺の順番はadd_edgeで追加された順番と同一。</para>
            /// <para>計算量: O(n)</para>
            /// </remarks>
            public List<Edge> Edges()
            {
                int m = _pos.Count;
                var result = new List<Edge>();
                for (int i = 0; i < m; i++)
                {
                    result.Add(GetEdge(i));
                }
                return result;
            }

            /// <summary>
            /// <paramref name="i"/> 番目に追加された辺の容量、流量を
            /// <paramref name="newCap"/>, <paramref name="newFlow"/> に変更します。
            /// </summary>
            /// <remarks>
            /// <para>
            /// 他の辺の容量、流量は変更しません。
            /// 辺 <paramref name="i"/> の流量、容量のみを
            /// <paramref name="newCap"/>, <paramref name="newFlow"/> へ変更します。
            /// </para>
            /// </remarks>
            public void ChangeEdge(int i, TValue newCap, TValue newFlow)
            {
                int m = _pos.Count;
                Debug.Assert(0 <= i && i < m);
                Debug.Assert(op.LessThanOrEqual(default, newFlow) && op.LessThanOrEqual(newFlow, newCap));
                var _e = _g[_pos[i].first][_pos[i].second];
                var _re = _g[_e.To][_e.Rev];
                _e.Cap = op.Subtract(newCap, newFlow);
                _re.Cap = newFlow;
            }

            /// <summary>
            /// 頂点 <paramref name="s"/> から <paramref name="t"/> へ流せる限り流し、
            /// 流せた量を返します。
            /// </summary>
            /// <remarks>
            /// <para>
            /// 複数回呼ぶことも可能で、その時の挙動は
            /// 変更前と変更後の流量を f_e, f'_e として、以下の条件を満たすように変更します。
            /// </para>
            /// <list type="bullet">
            /// <item>
            /// <description>0 ≤ f'_e ≤ C_e</description>
            /// </item>
            /// <item>
            /// <description>
            /// <paramref name="s"/>, <paramref name="t"/> 以外の頂天 v について、
            /// g(v, f) = g(v, f')
            /// </description>
            /// </item>
            /// <item>
            /// <description>
            /// (flowLimit を指定した場合) g(t, f') - g(t, f) ≤ flowLimit
            /// </description>
            /// </item>
            /// <item>
            /// <description>
            /// g(t, f') - g(t, f) が委譲の条件を満たすうち最大。この g(t, f') - g(t, f) を返す。
            /// </description>
            /// </item>
            /// </list>
            /// <para>制約: 返値が <typeparamref name="TValue"/> に収まる。</para>
            /// 計算量: m を追加された辺数として、
            /// <list type="bullet">
            /// <item>
            /// <description>O(min(n^(2/3) m, m^(3/2))) (辺の容量が全部 1 の時)</description>
            /// </item>
            /// <item>
            /// <description>O(n^2 m)</description>
            /// </item>
            /// </list>
            /// </remarks>
            public TValue Flow(int s, int t)
            {
                return Flow(s, t, op.MaxValue);
            }

            /// <summary>
            /// 頂点 <paramref name="s"/> から <paramref name="t"/> へ
            /// 流量 <paramref name="flowLimit"/> に達するまで流せる限り流し、
            /// 流せた量を返します。
            /// </summary>
            /// <remarks>
            /// <para>
            /// 複数回呼ぶことも可能で、その時の挙動は
            /// 変更前と変更後の流量を f_e, f'_e として、以下の条件を満たすように変更します。
            /// </para>
            /// <list type="bullet">
            /// <item>
            /// <description>0 ≤ f'_e ≤ C_e</description>
            /// </item>
            /// <item>
            /// <description>
            /// <paramref name="s"/>, <paramref name="t"/> 以外の頂天 v について、
            /// g(v, f) = g(v, f')
            /// </description>
            /// </item>
            /// <item>
            /// <description>
            /// (<paramref name="flowLimit"/> を指定した場合) g(t, f') - g(t, f) ≤ <paramref name="flowLimit"/>
            /// </description>
            /// </item>
            /// <item>
            /// <description>
            /// g(t, f') - g(t, f) が委譲の条件を満たすうち最大。この g(t, f') - g(t, f) を返す。
            /// </description>
            /// </item>
            /// </list>
            /// <para>制約: 返値が <typeparamref name="TValue"/> に収まる。</para>
            /// 計算量: m を追加された辺数として、
            /// <list type="bullet">
            /// <item>
            /// <description>O(min(n^(2/3) m, m^(3/2))) (辺の容量が全部 1 の時)</description>
            /// </item>
            /// <item>
            /// <description>O(n^2 m)</description>
            /// </item>
            /// </list>
            /// </remarks>
            public TValue Flow(int s, int t, TValue flowLimit)
            {
                Debug.Assert(0 <= s && s < _n);
                Debug.Assert(0 <= t && t < _n);

                var level = new int[_n];
                var iter = new int[_n];
                var que = new Queue<int>();

                void Bfs()
                {
                    for (int i = 0; i < _n; i++)
                    {
                        level[i] = -1;
                    }

                    level[s] = 0;
                    que.Clear();
                    que.Enqueue(s);
                    while (que.Count > 0)
                    {
                        int v = que.Dequeue();
                        foreach (var e in _g[v])
                        {
                            if (op.Equals(e.Cap, default) || level[e.To] >= 0) continue;
                            level[e.To] = level[v] + 1;
                            if (e.To == t) return;
                            que.Enqueue(e.To);
                        }
                    }
                }

                TValue Dfs(int v, TValue up)
                {
                    if (v == s) return up;
                    var res = default(TValue);
                    int level_v = level[v];
                    for (; iter[v] < _g[v].Count; iter[v]++)
                    {
                        EdgeInternal e = _g[v][iter[v]];
                        if (level_v <= level[e.To] || op.Equals(_g[e.To][e.Rev].Cap, default)) continue;
                        var up1 = op.Subtract(up, res);
                        var up2 = _g[e.To][e.Rev].Cap;
                        var d = Dfs(e.To, op.LessThan(up1, up2) ? up1 : up2);
                        if (op.Compare(d, default) <= 0) continue;
                        _g[v][iter[v]].Cap = op.Add(_g[v][iter[v]].Cap, d);
                        _g[e.To][e.Rev].Cap = op.Subtract(_g[e.To][e.Rev].Cap, d);
                        res = op.Add(res, d);
                        if (res.Equals(up)) break;
                    }

                    return res;
                }

                TValue flow = default;
                while (op.LessThan(flow, flowLimit))
                {
                    Bfs();
                    if (level[t] == -1) break;
                    for (int i = 0; i < _n; i++)
                    {
                        iter[i] = 0;
                    }
                    while (op.LessThan(flow, flowLimit))
                    {
                        var f = Dfs(t, op.Subtract(flowLimit, flow));
                        if (op.Equals(f, default)) break;
                        flow = op.Add(flow, f);
                    }
                }
                return flow;
            }

            /// <summary>
            /// 長さ n の配列を返します。
            /// i 番目の要素には、頂点 <paramref name="s"/> から i へ残余グラフで到達可能なとき、
            /// またその時のみ true を返します。
            /// Flow(s, t) を flowLimit なしでちょうど一回呼んだ後に呼ぶと、
            /// 返り値はs, t 間の mincut に対応します。
            /// </summary>
            /// <remarks>
            /// <para>
            /// 各辺 e = (u, v, f_e, c_e) について、 f_e &lt; c_e ならば辺 (u, v) を張り、
            /// 0 &lt; f_e ならば辺 (u, v) を張ったと仮定したとき、
            /// 頂点 ss から到達可能な頂点の集合を返します。
            /// </para>
            /// 計算量: m を追加された辺数として、
            /// <list type="bullet">
            /// <item>
            /// <description>O(n + m)</description>
            /// </item>
            /// </list>
            /// </remarks>
            public bool[] MinCut(int s)
            {
                var visited = new bool[_n];
                var que = new Queue<int>();
                que.Enqueue(s);
                while (que.Count > 0)
                {
                    int p = que.Dequeue();
                    visited[p] = true;
                    foreach (var e in _g[p])
                    {
                        if (!op.Equals(e.Cap, default) && !visited[e.To])
                        {
                            visited[e.To] = true;
                            que.Enqueue(e.To);
                        }
                    }
                }

                return visited;
            }

            /// <summary>
            /// フロー流すグラフの各辺に対応した情報を持ちます。
            /// </summary>
            public struct Edge
            {
                /// <summary>フローが流出する頂点。</summary>
                public int From { get; set; }
                /// <summary>フローが流入する頂点。</summary>
                public int To { get; set; }
                /// <summary>辺の容量。</summary>
                public TValue Cap { get; set; }
                /// <summary>辺の流量。</summary>
                public TValue Flow { get; set; }
                public Edge(int from, int to, TValue cap, TValue flow)
                {
                    From = from;
                    To = to;
                    Cap = cap;
                    Flow = flow;
                }
            };

            private class EdgeInternal
            {
                public int To { get; set; }
                public int Rev { get; set; }
                public TValue Cap { get; set; }
                public EdgeInternal(int to, int rev, TValue cap)
                {
                    To = to;
                    Rev = rev;
                    Cap = cap;
                }
            };

            private readonly int _n;
            private readonly List<(int first, int second)> _pos;
            private readonly List<EdgeInternal>[] _g;

        }
    }
}
namespace AtCoderLibraryPracticeContest
{
    class Program
    {
        static void Main(string[] args)
        {
            IAtCoderQuestion question = new QuestionD();
            var answers = question.Solve(Console.In);

            var writer = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            Console.SetOut(writer);
            foreach (var answer in answers)
            {
                Console.WriteLine(answer);
            }
            Console.Out.Flush();
        }
    }
}

namespace AtCoder
{
    public class DSU
    {
        private int Count;
        private int[] ParentOrSize;

        /// <summary>
        /// <see cref="DSU"/> クラスの新しいインスタンスを、<paramref name="n"/> 頂点 0 辺のグラフとして初期化します。
        /// </summary>
        /// <remarks>
        /// <para>制約: 0≤<paramref name="n"/>≤10^8</para>
        /// <para>計算量: O(<paramref name="n"/>)</para>
        /// </remarks>
        public DSU(int n)
        {
            Count = n;
            ParentOrSize = new int[n];
            for (int i = 0; i < ParentOrSize.Length; i++) ParentOrSize[i] = -1;
        }

        /// <summary>
        /// 頂点 <paramref name="a"/> と頂点 <paramref name="b"/> を結ぶ辺を追加し、それらの代表元を返します。
        /// </summary>
        /// <remarks>
        /// <para>制約: 0≤<paramref name="a"/>, <paramref name="b"/>&lt;n</para>
        /// <para>計算量: ならしO(a(n))</para>
        /// </remarks>
        public int Merge(int a, int b)
        {
            Debug.Assert(0 <= a && a < Count);
            Debug.Assert(0 <= b && b < Count);
            int x = Leader(a), y = Leader(b);
            if (x == y) return x;
            if (-ParentOrSize[x] < ParentOrSize[y]) (x, y) = (y, x);
            ParentOrSize[x] += ParentOrSize[y];
            ParentOrSize[y] = x;
            return x;
        }

        /// <summary>
        /// 頂点 <paramref name="a"/>, <paramref name="b"/> が連結かどうかを返します。
        /// </summary>
        /// <remarks>
        /// <para>制約: 0≤<paramref name="a"/>, <paramref name="b"/>&lt;n</para>
        /// <para>計算量: ならしO(a(n))</para>
        /// </remarks>
        public bool Same(int a, int b)
        {
            Debug.Assert(0 <= a && a < Count);
            Debug.Assert(0 <= b && b < Count);
            return Leader(a) == Leader(b);
        }

        /// <summary>
        /// 頂点 <paramref name="a"/> の属する連結成分の代表元を返します。
        /// </summary>
        /// <remarks>
        /// <para>制約: 0≤<paramref name="a"/>&lt;n</para>
        /// <para>計算量: ならしO(a(n))</para>
        /// </remarks>
        public int Leader(int a)
        {
            if (ParentOrSize[a] < 0) return a;
            while (0 <= ParentOrSize[ParentOrSize[a]])
            {
                (a, ParentOrSize[a]) = (ParentOrSize[a], ParentOrSize[ParentOrSize[a]]);
            }
            return ParentOrSize[a];
        }


        /// <summary>
        /// 頂点 <paramref name="a"/> の属する連結成分のサイズを返します。
        /// </summary>
        /// <remarks>
        /// <para>制約: 0≤<paramref name="a"/>&lt;n</para>
        /// <para>計算量: ならしO(a(n))</para>
        /// </remarks>
        public int Size(int a)
        {
            Debug.Assert(0 <= a && a < Count);
            return -ParentOrSize[Leader(a)];
        }

        /// <summary>
        /// グラフを連結成分に分け、その情報を返します。
        /// </summary>
        /// <para>計算量: O(n)</para>
        /// <returns>「一つの連結成分の頂点番号のリスト」のリスト。</returns>
        public Span<int[]> Groups()
        {
            int[] leaderBuf = new int[Count];
            int[] id = new int[Count];
            Span<int[]> result = new int[Count][];
            int groupCount = 0;
            for (int i = 0; i < leaderBuf.Length; i++)
            {
                leaderBuf[i] = Leader(i);
                if (i == leaderBuf[i])
                {
                    id[i] = groupCount;
                    result[id[i]] = new int[-ParentOrSize[i]];
                    groupCount++;
                }
            }
            int[] ind = new int[groupCount];
            result = result.Slice(0, groupCount);
            for (int i = 0; i < leaderBuf.Length; i++)
            {
                var leaderID = id[leaderBuf[i]];
                result[leaderID][ind[leaderID]] = i;
                ind[leaderID]++;
            }
            return result;
        }
    }
}

namespace AtCoder
{
#pragma warning disable CA1815 // Override equals and operator equals on value types
    public interface INumOperator<T> : IEqualityComparer<T>, IComparer<T> where T : struct
    {
        /// <summary>
        /// MinValue
        /// </summary>
        public T MinValue { get; }
        /// <summary>
        /// MaxValue
        /// </summary>
        public T MaxValue { get; }
        /// <summary>
        /// Addition operator +
        /// </summary>
        /// <returns><paramref name="x"/> + <paramref name="y"/></returns>
        T Add(T x, T y);
        /// <summary>
        /// Subtraction operator -
        /// </summary>
        /// <returns><paramref name="x"/> - <paramref name="y"/></returns>
        T Subtract(T x, T y);
        /// <summary>
        /// Multiplication operator *
        /// </summary>
        /// <returns><paramref name="x"/> * <paramref name="y"/></returns>
        T Multiply(T x, T y);
        /// <summary>
        /// Division operator /
        /// </summary>
        /// <returns><paramref name="x"/> / <paramref name="y"/></returns>
        T Divide(T x, T y);
        /// <summary>
        /// Remainder operator %
        /// </summary>
        /// <returns><paramref name="x"/> % <paramref name="y"/></returns>
        T Modulo(T x, T y);
        /// <summary>
        /// Greater than operator &gt;
        /// </summary>
        /// <returns><paramref name="x"/> &gt; <paramref name="y"/></returns>
        bool GreaterThan(T x, T y);
        /// <summary>
        /// Greater than or equal operator &gt;=
        /// </summary>
        /// <returns><paramref name="x"/> &gt;= <paramref name="y"/></returns>
        bool GreaterThanOrEqual(T x, T y);
        /// <summary>
        /// Less than operator &lt;
        /// </summary>
        /// <returns><paramref name="x"/> &lt; <paramref name="y"/></returns>
        bool LessThan(T x, T y);
        /// <summary>
        /// Less than or equal operator &lt;=
        /// </summary>
        /// <returns><paramref name="x"/> &lt;= <paramref name="y"/></returns>
        bool LessThanOrEqual(T x, T y);
    }
    public readonly struct IntOperator : INumOperator<int>
    {
        public int MinValue => int.MinValue;
        public int MaxValue => int.MaxValue;
        public int Add(int x, int y) => x + y;
        public int Subtract(int x, int y) => x - y;
        public int Multiply(int x, int y) => x * y;
        public int Divide(int x, int y) => x / y;
        public int Modulo(int x, int y) => x % y;
        public bool GreaterThan(int x, int y) => x > y;
        public bool GreaterThanOrEqual(int x, int y) => x >= y;
        public bool LessThan(int x, int y) => x < y;
        public bool LessThanOrEqual(int x, int y) => x <= y;
        public int Compare(int x, int y) => x.CompareTo(y);
        public bool Equals(int x, int y) => x == y;
        public int GetHashCode(int obj) => obj.GetHashCode();
    }
    public readonly struct LongOperator : INumOperator<long>
    {
        public long MinValue => long.MinValue;
        public long MaxValue => long.MaxValue;
        public long Add(long x, long y) => x + y;
        public long Subtract(long x, long y) => x - y;
        public long Multiply(long x, long y) => x * y;
        public long Divide(long x, long y) => x / y;
        public long Modulo(long x, long y) => x % y;
        public bool GreaterThan(long x, long y) => x > y;
        public bool GreaterThanOrEqual(long x, long y) => x >= y;
        public bool LessThan(long x, long y) => x < y;
        public bool LessThanOrEqual(long x, long y) => x <= y;
        public int Compare(long x, long y) => x.CompareTo(y);
        public bool Equals(long x, long y) => x == y;
        public int GetHashCode(long obj) => obj.GetHashCode();
    }
    public readonly struct UIntOperator : INumOperator<uint>
    {
        public uint MinValue => uint.MinValue;
        public uint MaxValue => uint.MaxValue;
        public uint Add(uint x, uint y) => x + y;
        public uint Subtract(uint x, uint y) => x - y;
        public uint Multiply(uint x, uint y) => x * y;
        public uint Divide(uint x, uint y) => x / y;
        public uint Modulo(uint x, uint y) => x % y;
        public bool GreaterThan(uint x, uint y) => x > y;
        public bool GreaterThanOrEqual(uint x, uint y) => x >= y;
        public bool LessThan(uint x, uint y) => x < y;
        public bool LessThanOrEqual(uint x, uint y) => x <= y;
        public int Compare(uint x, uint y) => x.CompareTo(y);
        public bool Equals(uint x, uint y) => x == y;
        public int GetHashCode(uint obj) => obj.GetHashCode();
    }
    public readonly struct ULongOperator : INumOperator<ulong>
    {
        public ulong MinValue => ulong.MinValue;
        public ulong MaxValue => ulong.MaxValue;
        public ulong Add(ulong x, ulong y) => x + y;
        public ulong Subtract(ulong x, ulong y) => x - y;
        public ulong Multiply(ulong x, ulong y) => x * y;
        public ulong Divide(ulong x, ulong y) => x / y;
        public ulong Modulo(ulong x, ulong y) => x % y;
        public bool GreaterThan(ulong x, ulong y) => x > y;
        public bool GreaterThanOrEqual(ulong x, ulong y) => x >= y;
        public bool LessThan(ulong x, ulong y) => x < y;
        public bool LessThanOrEqual(ulong x, ulong y) => x <= y;
        public int Compare(ulong x, ulong y) => x.CompareTo(y);
        public bool Equals(ulong x, ulong y) => x == y;
        public int GetHashCode(ulong obj) => obj.GetHashCode();
    }
    public readonly struct DoubleOperator : INumOperator<double>
    {
        public double MinValue => double.MinValue;
        public double MaxValue => double.MaxValue;
        public double Add(double x, double y) => x + y;
        public double Subtract(double x, double y) => x - y;
        public double Multiply(double x, double y) => x * y;
        public double Divide(double x, double y) => x / y;
        public double Modulo(double x, double y) => x % y;
        public bool GreaterThan(double x, double y) => x > y;
        public bool GreaterThanOrEqual(double x, double y) => x >= y;
        public bool LessThan(double x, double y) => x < y;
        public bool LessThanOrEqual(double x, double y) => x <= y;
        public int Compare(double x, double y) => x.CompareTo(y);
        public bool Equals(double x, double y) => x == y;
        public int GetHashCode(double obj) => obj.GetHashCode();
    }
#pragma warning restore CA1815 // Override equals and operator equals on value types
}

namespace AtCoder.Internal
{
    public static class InternalBit
    {
        /// <summary>
        /// _blsi_u32 OR <paramref name="n"/> &amp; -<paramref name="n"/>
        /// <para><paramref name="n"/>で立っているうちの最下位の 1 ビットのみを立てた整数を返す</para>
        /// </summary>
        /// <param name="n"></param>
        /// <returns><paramref name="n"/> &amp; -<paramref name="n"/></returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int ExtractLowestSetBit(int n)
        {
            if (Bmi1.IsSupported)
            {
                return (int)Bmi1.ExtractLowestSetBit((uint)n);
            }
            return n & -n;
        }

        /// <summary>
        /// (<paramref name="n"/> &amp; (1 &lt;&lt; x)) != 0 なる最小の非負整数 x を求めます。
        /// </summary>
        /// <remarks>
        /// <para>BSF: Bit Scan Forward</para>
        /// <para>制約: 1 ≤ <paramref name="n"/></para>
        /// </remarks>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int BSF(uint n)
        {
            Debug.Assert(n >= 1);
            if (Bmi1.IsSupported)
            {
                // O(1)
                return (int)Bmi1.TrailingZeroCount(n);
            }
            else if (Popcnt.IsSupported)
            {
                // O(1)
                return (int)Popcnt.PopCount(~n & (n - 1));
            }
            else
            {
                // O(logn)
                return BitOperations.TrailingZeroCount(n);
            }
        }
    }
}

namespace AtCoder
{

    /// <summary>
    /// 長さ N の配列に対し、
    /// <list type="bullet">
    /// <item>
    /// <description>要素の 1 点変更</description>
    /// </item>
    /// <item>
    /// <description>区間の要素の総和</description>
    /// </item>
    /// </list>
    /// <para>を O(log⁡N) で求めることが出来るデータ構造です。</para>
    /// </summary>
    public class IntFenwickTree : FenwickTree<int, IntOperator> { public IntFenwickTree(int n) : base(n) { } }

    /// <summary>
    /// 長さ N の配列に対し、
    /// <list type="bullet">
    /// <item>
    /// <description>要素の 1 点変更</description>
    /// </item>
    /// <item>
    /// <description>区間の要素の総和</description>
    /// </item>
    /// </list>
    /// <para>を O(log⁡N) で求めることが出来るデータ構造です。</para>
    /// </summary>
    public class UIntFenwickTree : FenwickTree<uint, UIntOperator> { public UIntFenwickTree(int n) : base(n) { } }

    /// <summary>
    /// 長さ N の配列に対し、
    /// <list type="bullet">
    /// <item>
    /// <description>要素の 1 点変更</description>
    /// </item>
    /// <item>
    /// <description>区間の要素の総和</description>
    /// </item>
    /// </list>
    /// <para>を O(log⁡N) で求めることが出来るデータ構造です。</para>
    /// </summary>
    public class LongFenwickTree : FenwickTree<long, LongOperator> { public LongFenwickTree(int n) : base(n) { } }

    /// <summary>
    /// 長さ N の配列に対し、
    /// <list type="bullet">
    /// <item>
    /// <description>要素の 1 点変更</description>
    /// </item>
    /// <item>
    /// <description>区間の要素の総和</description>
    /// </item>
    /// </list>
    /// <para>を O(log⁡N) で求めることが出来るデータ構造です。</para>
    /// </summary>
    public class ULongFenwickTree : FenwickTree<ulong, ULongOperator> { public ULongFenwickTree(int n) : base(n) { } }

    /// <summary>
    /// 長さ N の配列に対し、
    /// <list type="bullet">
    /// <item>
    /// <description>要素の 1 点変更</description>
    /// </item>
    /// <item>
    /// <description>区間の要素の総和</description>
    /// </item>
    /// </list>
    /// <para>を O(log⁡N) で求めることが出来るデータ構造です。</para>
    /// </summary>
    // TODO: public class ModIntFenwickTree : FenwickTree<ModInt, ModIntOperator> { public ModIntFenwickTree(int n) : base(n) { } }


    /// <summary>
    /// 長さ N の配列に対し、
    /// <list type="bullet">
    /// <item>
    /// <description>要素の 1 点変更</description>
    /// </item>
    /// <item>
    /// <description>区間の要素の総和</description>
    /// </item>
    /// </list>
    /// <para>を O(log⁡N) で求めることが出来るデータ構造です。</para>
    /// </summary>
    /// <typeparam name="TValue">配列要素の型</typeparam>
    /// <typeparam name="TOp">配列要素の操作を表す型</typeparam>
    [DebuggerTypeProxy(typeof(FenwickTree<,>.DebugView))]
    public class FenwickTree<TValue, TOp>
        where TValue : struct
        where TOp : struct, INumOperator<TValue>
    {
        private static readonly TOp op = default;
        private readonly TValue[] data;

        /// <summary>
        /// 長さ <paramref name="n"/> の配列aを持つ <see cref="FenwickTree{TValue, TOp}"/> クラスの新しいインスタンスを作ります。
        /// </summary>
        /// <remarks>
        /// <para>制約: 0≤<paramref name="n"/>≤10^8</para>
        /// <para>計算量: O(<paramref name="n"/>)</para>
        /// </remarks>
        /// <param name="n">配列の長さ</param>
        public FenwickTree(int n)
        {
            Debug.Assert(unchecked((uint)n <= 100_000_000));
            data = new TValue[n + 1];
        }

        /// <summary>
        /// a[<paramref name="p"/>] += <paramref name="x"/> を行います。
        /// </summary>
        /// <remarks>
        /// <para>制約: 0≤<paramref name="p"/>&lt;n</para>
        /// <para>計算量: O(log n)</para>
        /// </remarks>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Add(int p, TValue x)
        {
            Debug.Assert(unchecked((uint)p < data.Length));
            for (p++; p < data.Length; p += InternalBit.ExtractLowestSetBit(p))
            {
                data[p] = op.Add(data[p], x);
            }
        }

        /// <summary>
        /// a[<paramref name="l"/>] + a[<paramref name="l"/> - 1] + ... + a[<paramref name="r"/> - 1] を返します。
        /// </summary>
        /// <remarks>
        /// <para>制約: 0≤<paramref name="l"/>≤<paramref name="r"/>≤n</para>
        /// <para>計算量: O(log n)</para>
        /// </remarks>
        /// <returns>a[<paramref name="l"/>] + a[<paramref name="l"/> - 1] + ... + a[<paramref name="r"/> - 1]</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public TValue Sum(int l, int r)
        {
            Debug.Assert(0 <= l && l <= r && r < data.Length);
            return op.Subtract(Sum(r), Sum(l));
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private TValue Sum(int r)
        {
            TValue s = default;
            for (; r > 0; r -= InternalBit.ExtractLowestSetBit(r))
            {
                s = op.Add(s, data[r]);
            }
            return s;
        }


        [DebuggerDisplay("Value = {" + nameof(value) + "}, Sum = {" + nameof(sum) + "}")]
        private struct DebugItem
        {
            public DebugItem(TValue value, TValue sum)
            {
                this.sum = sum;
                this.value = value;
            }
            [DebuggerBrowsable(DebuggerBrowsableState.Never)]
            public readonly TValue value;
            [DebuggerBrowsable(DebuggerBrowsableState.Never)]
            public readonly TValue sum;
        }
        private class DebugView
        {
            private readonly FenwickTree<TValue, TOp> fenwickTree;
            public DebugView(FenwickTree<TValue, TOp> fenwickTree)
            {
                this.fenwickTree = fenwickTree;
            }
            [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
            public DebugItem[] Items
            {
                get
                {
                    var data = fenwickTree.data;
                    var items = new DebugItem[data.Length - 1];
                    items[0] = new DebugItem(data[1], data[1]);
                    for (int i = 2; i < data.Length; i++)
                    {
                        int length = InternalBit.ExtractLowestSetBit(i);
                        var pr = i - length - 1;
                        var sum = op.Add(data[i], 0 <= pr ? items[pr].sum : default);
                        var val = op.Subtract(sum, items[i - 2].sum);
                        items[i - 1] = new DebugItem(val, sum);
                    }
                    return items;
                }
            }
        }
    }
}

#region Base Class

namespace AtCoderLibraryPracticeContest.Questions
{

    public interface IAtCoderQuestion
    {
        IEnumerable<object> Solve(string input);
        IEnumerable<object> Solve(TextReader inputStream);
    }

    public abstract class AtCoderQuestionBase : IAtCoderQuestion
    {
        public IEnumerable<object> Solve(string input)
        {
            var stream = new MemoryStream(Encoding.Unicode.GetBytes(input));
            var reader = new StreamReader(stream, Encoding.Unicode);

            return Solve(reader);
        }

        public abstract IEnumerable<object> Solve(TextReader inputStream);
    }
}

#endregion

#region Extensions

namespace AtCoderLibraryPracticeContest.Extensions
{
    public static class StringExtensions
    {
        public static string Join<T>(this IEnumerable<T> source) => string.Concat(source);
        public static string Join<T>(this IEnumerable<T> source, char separator) => string.Join(separator, source);
        public static string Join<T>(this IEnumerable<T> source, string separator) => string.Join(separator, source);
    }

    public static class TextReaderExtensions
    {
        public static int ReadInt(this TextReader reader) => int.Parse(ReadString(reader));
        public static long ReadLong(this TextReader reader) => long.Parse(ReadString(reader));
        public static double ReadDouble(this TextReader reader) => double.Parse(ReadString(reader));
        public static string ReadString(this TextReader reader) => reader.ReadLine();

        public static int[] ReadIntArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(int.Parse).ToArray();
        public static long[] ReadLongArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(long.Parse).ToArray();
        public static double[] ReadDoubleArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(double.Parse).ToArray();
        public static string[] ReadStringArray(this TextReader reader, char separator = ' ') => reader.ReadLine().Split(separator);

        // Supports primitive type only.
        public static T1 ReadValue<T1>(this TextReader reader) => (T1)Convert.ChangeType(reader.ReadLine(), typeof(T1));

        public static (T1, T2) ReadValue<T1, T2>(this TextReader reader, char separator = ' ')
        {
            var inputs = ReadStringArray(reader, separator);
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            return (v1, v2);
        }

        public static (T1, T2, T3) ReadValue<T1, T2, T3>(this TextReader reader, char separator = ' ')
        {
            var inputs = ReadStringArray(reader, separator);
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            var v3 = (T3)Convert.ChangeType(inputs[2], typeof(T3));
            return (v1, v2, v3);
        }

        public static (T1, T2, T3, T4) ReadValue<T1, T2, T3, T4>(this TextReader reader, char separator = ' ')
        {
            var inputs = ReadStringArray(reader, separator);
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            var v3 = (T3)Convert.ChangeType(inputs[2], typeof(T3));
            var v4 = (T4)Convert.ChangeType(inputs[3], typeof(T4));
            return (v1, v2, v3, v4);
        }

        public static (T1, T2, T3, T4, T5) ReadValue<T1, T2, T3, T4, T5>(this TextReader reader, char separator = ' ')
        {
            var inputs = ReadStringArray(reader, separator);
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            var v3 = (T3)Convert.ChangeType(inputs[2], typeof(T3));
            var v4 = (T4)Convert.ChangeType(inputs[3], typeof(T4));
            var v5 = (T5)Convert.ChangeType(inputs[4], typeof(T5));
            return (v1, v2, v3, v4, v5);
        }

        public static (T1, T2, T3, T4, T5, T6) ReadValue<T1, T2, T3, T4, T5, T6>(this TextReader reader, char separator = ' ')
        {
            var inputs = ReadStringArray(reader, separator);
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            var v3 = (T3)Convert.ChangeType(inputs[2], typeof(T3));
            var v4 = (T4)Convert.ChangeType(inputs[3], typeof(T4));
            var v5 = (T5)Convert.ChangeType(inputs[4], typeof(T5));
            var v6 = (T6)Convert.ChangeType(inputs[5], typeof(T6));
            return (v1, v2, v3, v4, v5, v6);
        }

        public static (T1, T2, T3, T4, T5, T6, T7) ReadValue<T1, T2, T3, T4, T5, T6, T7>(this TextReader reader, char separator = ' ')
        {
            var inputs = ReadStringArray(reader, separator);
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            var v3 = (T3)Convert.ChangeType(inputs[2], typeof(T3));
            var v4 = (T4)Convert.ChangeType(inputs[3], typeof(T4));
            var v5 = (T5)Convert.ChangeType(inputs[4], typeof(T5));
            var v6 = (T6)Convert.ChangeType(inputs[5], typeof(T6));
            var v7 = (T7)Convert.ChangeType(inputs[6], typeof(T7));
            return (v1, v2, v3, v4, v5, v6, v7);
        }

        public static (T1, T2, T3, T4, T5, T6, T7, T8) ReadValue<T1, T2, T3, T4, T5, T6, T7, T8>(this TextReader reader, char separator = ' ')
        {
            var inputs = ReadStringArray(reader, separator);
            var v1 = (T1)Convert.ChangeType(inputs[0], typeof(T1));
            var v2 = (T2)Convert.ChangeType(inputs[1], typeof(T2));
            var v3 = (T3)Convert.ChangeType(inputs[2], typeof(T3));
            var v4 = (T4)Convert.ChangeType(inputs[3], typeof(T4));
            var v5 = (T5)Convert.ChangeType(inputs[4], typeof(T5));
            var v6 = (T6)Convert.ChangeType(inputs[5], typeof(T6));
            var v7 = (T7)Convert.ChangeType(inputs[6], typeof(T7));
            var v8 = (T8)Convert.ChangeType(inputs[7], typeof(T8));
            return (v1, v2, v3, v4, v5, v6, v7, v8);
        }
    }
}

#endregion