AtCoder NoviStepsを埋めてみる(16) 集合(set)の続きです。今回は 連想配列(map)の問題です。C#にはキーと値のペアを格納するデータ構造である Dictionary があり、連想配列に似た操作ができます。

C – Poll

C – Poll

問題の概要

N 個の文字列が与えられる。
回数が最も多い文字列をすべて辞書順で小さい順に出力せよ。

Dictionary で出現回数を数え、もっとも回数が多かったものと同じ回数の文字列を取得してソートして出力するだけです。

D – Diversity of Scores

D – Diversity of Scores

問題の概要

長さ N の配列 X があり、最初はすべての要素が 0 である。
T 回にわたって X[A[i]] が B[i] だけ増加する。
各更新が終わったときに配列内に何種類の値が現れるか出力せよ。

Dictionary でどの値が何個あるかを持つようにすれば TLE することなく AC できます。

C – Colorful Candies

C – Colorful Candies

A – Zero-Sum Ranges

A – Zero-Sum Ranges

問題の概要

長さ N の整数列 A が与えられる。
A の 空でない 連続する 部分列であって、その総和が 0 になるものの個数を求めよ。

累積和(A[0] から A[i] までの総和を sums[i + 1] とする)を考えます。sums[b] – sums[a] = 0 (b > a) であれば A[a + 1] から A[b] までの総和は 0 です。なので sums[i] = x となる i の個数 cnt[x] を数えます。cnt[x] * (cnt[x] – 1) / 2 の総和が出力すべき解となります。

D – Count Interval

D – Count Interval

長さ N の数列 A と 整数 K が与えられる。
A の連続部分列のうち、要素の和が K になるものはいくつあるか求めよ。

A – Zero-Sum Ranges と似ていますが、今回は K = 0 とは限りません。

この場合も累積和を使えばよいです。sums[a] = x であれば b > a かつ a sums[b] = x + K を満たす b の個数を数えることになります。dic に x の個数を格納して a に相当するデータを取り除きながら数えればよいです。

D – Kadomatsu Subsequence

D – Kadomatsu Subsequence

問題の概要

長さ N の整数列 A が与えられる。
以下をすべて満たす整数の 3 つ組 (i, j, k) がいくつあるか求めよ。
(条件 1) A[i] : A[j] : A[k] = 7 : 5 : 3
(条件 2) min(i, j, k) = j または max(i, j, k) = j

min(i, j, k) = j のものを探す方法を考えます。j < i, k という条件で A[i] : A[j] : A[k] = 7 : 5 : 3 となるものを探します。そのためには dic に A[i] の値と出現回数を格納して、i に相当する値を削除してから (条件 1) を満たすものの個数を数えればよいです。max(i, j, k) = j のものを数えるときは A を反転して同じようなことをすればよいです。

E – This Message Will Self-Destruct in 5s

E – This Message Will Self-Destruct in 5s

問題の概要

N 人の人がいる。人 i の身長は A[i] である。
「2 人の持つ番号の差の絶対値が、2 人の身長の和に等しい」
このようなペアは何通りあるか求めよ。

i < j とすると求めるものは、j – i = A[i] + A[j] を満たすペアの数です。この条件式を変形すると、i + A[i] = j – A[j] となります。

j – A[j] となる j の個数を数えておき、i + A[i] であるものがそれぞれ何個あるかを調べます。するとその総和が求めるべき解となります。

D – Candy Distribution

D – Candy Distribution

問題の概要

長さ N の整数列 A が与えられる。
A の 空でない 連続する 部分列であって、その総和が M の倍数 になるものの個数を求めよ。

M で割った剰余の累積和を考えます。あとは A – Zero-Sum Ranges と同じです。

D – Takahashi’s Solitaire

D – Takahashi’s Solitaire

長さ N の非負整数列 A が与えられる。
最初に A のなかからある値 X を選ぶ。
X または (X + 1) mod M である要素があるなら取り除き、その値で X を更新する。
これを繰り返して A のなかに残された値の総和を最小化したい。最小値を求めよ。

dic で同じ値をひとつにまとめて、Key がつながっている(差が 1)ものをひとつのグループにします。このとき dic のなかに 0 と M – 1 があればつながっていることになるのでそれも同じグループにします。

グループごとの総和を求めます。これが操作によって取り除くことができる要素の総和です。ここから取り除かれずに残される値の総和を求め、最小のものを出力します。

A – 碁石ならべ 2 (Stone Arranging 2)

A – 碁石ならべ 2 (Stone Arranging 2)

問題の概要

碁石を左から右へ順番に並べる。
途中でそれよりも左にある碁石で同じ色のものがある場合、そのあいだにある碁石はすべてその色で塗り替える。
すべての操作を行った後の碁石の色をそれぞれ出力せよ。

同じ色であれば必ずひとつながりの連続した区間になります(飛び地には絶対にならない)。

最後にその色が現れた index を dic に記録しておきます。また Stack に(色、その色がはじまる最初の index、その色が終わる最後の index)を格納していきます。

もし左側に置かれている碁石と同じ色の碁石を置くときは同じ色のものが現れるまで Stack を pop します。そしてその色がはじまる最初と最後の index の情報を更新します。また pop された他の色に関する情報は色が塗り替えられるので dic からも削除します。

最後に Stack に残されている情報から各碁石の色を求めて出力します。

origami – 折り紙 (Origami)

origami – 折り紙 (Origami)

問題の概要

横 a cm,縦 b cm の長方形の台紙がある。この台紙には 1 cm おきに辺に平行になるように縦横に直線が引かれ、全体で a × b 個の一辺 1 cm の正方形の格子ができるように区切られている。
左から x 列目、下から y 行目の格子を (x, y) と表す。
台紙の上に n 枚の長方形の紙を順番に貼っていく。紙を貼る位置は 4 つの整数の組 (p, q, r, s) で指定され、格子 (p, q), (p, s), (r, q), (r, s) が紙の角になるように貼っていく。
紙が最も多く重なっている部分が何枚重ねなのか、またその部分の合計の面積を求めよ。

a × b が大きな値なので二次元配列を定義してシミュレーションすることができません。座圧して最も紙が厚くなっている部分を調べます。