概要
久々の投稿になります。
トヨタシステムズプログラミングコンテスト2023(AtCoder Beginner Contest 330)のC#実装例です。ロジックの解説は公式をご覧ください。
A - Counting Passes
LINQ最高!
static void Main()
{
var l = int.Parse(ReadLine().Split()[1]);
var aa = ReadLine().Split().Select(int.Parse);
WriteLine(aa.Count(a => a >= l));
}
B - Minimize Abs 1
問題文の読解が最大の難関。
三項演算子が使えればスマートでしょう。
static void Main()
{
var (n, l, r) = ReadLine().Split().Select(int.Parse);
var aa = ReadLine().Split().Select(int.Parse);
WriteLine(string.Join(' ', aa.Select(a => a < l ? l : a < r ? a : r)));
}
C - Minimize Abs 2
公式解説にあまり付け加えることがないです。
static void Main()
{
var d = long.Parse(ReadLine());
var xMax = (long)Math.Sqrt(d) + 1;
var min = long.MaxValue;
for (var x = 1L; x <= xMax; x++)
{
var x2 = x * x;
var y = (long)Math.Sqrt(Math.Max(d - x2, 0));
min = Math.Min(min, Math.Abs(x2 + y * y - d));
min = Math.Min(min, Math.Abs(x2 + (y + 1) * (y + 1) - d));
}
WriteLine(min);
}
D - Counting Ls
交点のマスに注目することに気づかずTLEしました。
countsBy~あたりはLINQの本領発揮といったところでしょうか。
最後のループはLINQでも書けますが、ベタに書いたほうがよいでしょう。
countをintで宣言すると死にます。
static void Main()
{
var n = ReadLine();
var ss = readLines().ToArray();
var countsByRow = ss.Select(s => s.Count(c => c == 'o')).ToArray();
var countsByColumn = Enumerable.Range(0, ss.Length).Select(i => ss.Count(s => s[i] == 'o')).ToArray();
var count = 0L;
for (var i = 0; i < ss.Length; i++)
{
for (var j = 0; j < ss.Length; j++)
{
if (ss[i][j] == 'o'){count += (countsByRow[i] - 1) * (countsByColumn[j] - 1);}
}
}
WriteLine(count);
}
E - Mex and Update
配列を更新しながらMEXを出力する問題。
データ構造の選択がポイントですが、C#ではSortedSetが使えます。内部は二分木らしいので十分高速です。
なお間に合ったので省略しましたが、出力にバッファを挟んで1回のWriteで済ませることを検討したほうがよいでしょう。
static void Main()
{
var (n, q) = ReadLine().Split().Select(int.Parse);
var aa = ReadLine().Split().Select(int.Parse).ToArray();
// Aの値と個数
var counts = aa.GroupBy(a => a).ToDictionary(g => g.Key, g => g.Count());
// Aに含まれない値
var exs = new SortedSet<int>(Enumerable.Range(0, n + 1).Where(i => !counts.ContainsKey(i)));
var ixs = readLines().Select(s => s.Split().Select(int.Parse).ToArray());
foreach (var ix in ixs)
{
var (i, x) = ix;
var pre = aa[i - 1];
if (pre != x)
{
// 入れ替えして個数0・以外になったらexsを出し入れ
aa[i - 1] = x;
counts[pre]--;
if (counts.ContainsKey(x) && counts[x] > 0) { counts[x]++; } else { counts[x] = 1; exs.Remove(x); }
if (counts[pre] == 0) { exs.Add(pre); }
}
WriteLine(exs.Min);
}
}
共通コード
もっと用意してありますが、今回使ったのはこのくらい。 Deconstructはいいですよね。using System;
using System.Collections.Generic;
using System.Linq;
using static System.Console;
static class Program
{
static IEnumerable<string> readLines()
{
for (var s = ReadLine(); !string.IsNullOrEmpty(s); s = ReadLine()){yield return s;}
}
// var (x, y) = ReadLine().Split(); と書けるようになる。
static void Deconstruct<T>(this IEnumerable<T> source, out T item1, out T item2)
{
using var e = source.GetEnumerator();
e.MoveNext(); item1 = e.Current;
e.MoveNext(); item2 = e.Current;
}
static void Deconstruct<T>(this IEnumerable<T> source, out T item1, out T item2, out T item3)
{
using var e = source.GetEnumerator();
e.MoveNext(); item1 = e.Current;
e.MoveNext(); item2 = e.Current;
e.MoveNext(); item3 = e.Current;
}
}
以上、今回はコンテスト中に4完、解説読んでEを回答しました。精進します。