WCPC
AtCoder

ABC468参加記

2026年7月25日 N nsubaru

前回の参加記(ABC467回)

はじめに

こんにちは。nsubaruです。

上振れ青パフォで+104!入水しました!!!!🩵🩵🩵🩵

[入水した図]

初の青パフォでしかも1890パフォ、初の6完でしかも1時間切り、上振れに上振れました!

前回のABCで負けてレートが1124だったので今回もまだ水色にはなれないだろうなって感じで始まったのですが、 トントン拍子に問題を解くことができ、終わってみれば6完という結果になりました!

結果サマリ

問題参加者名タイム言語
Ansubaru0:36Java
BShoboiNamae5:10C++
CShoboiNamae9:02C++
DShoboiNamae39:25C++
Ensubaru32:41Java
Fnsubaru54:37Java
G---

今週の出題

ABC468-A

問題ページ: A問題

問題文を表示

問題文

長さ NN の整数列 A=(A1,A2,,AN)A=(A_1,A_2,\ldots,A_N) が与えられます。

Ai<Ai+1>Ai+2A_i \lt A_{i+1} > A_{i+2} を満たす 11 以上 N2N-2 以下の整数 ii の個数を求めてください。

制約

  • 3N1003\le N\le 100
  • 1Ai1001\le A_i\le 100
  • 入力される値は全て整数

入力

入力は以下の形式で標準入力から与えられる。

NN
A1A_1 A2A_2 \ldots ANA_N

出力

答えを出力せよ。

ICPC2022の国内予選と同じ問題ですね。 極大値のカウントということで、配列用のライブラリに用意していました! ArrayUtils.localMaxCnt() 関数を用いることで一瞬です!

ABC468-B

問題ページ: B問題

問題文を表示

問題文

整数 M,DM,D と、 G, . からなる長さ MM の文字列 SS が与えられます。

MM 個のマスが左右に一列に並んでおり、左から順にそれぞれ 11 から MM までの番号がついています。

いくつかのマスにはガードマンが立っています。具体的には、Si=S_i= G ならばマス ii にはガードマンが立っており、Si=S_i= . ならばマス ii には誰も立っていません。

ガードマンが立っているマスからの距離が DD 以下であるマスはガードマンによって監視されます。すなわち、あるマス ii が存在して Si=S_i= G かつ xiD|x-i|\le D を満たすマス xx はガードマンによって監視されます。

MM 個のマスのうち、監視されていないマスの個数を求めてください。

制約

  • 0D<M1000\le D \lt M \le 100
  • D,MD,M は整数
  • SiS_iG. からなる長さ MM の文字列

入力

入力は以下の形式で標準入力から与えられる。

MM DD
SS

出力

答えを出力せよ。

B問題にしてはめんどくさいなという印象。まあでも難易度的には順当かなという感じです。

G の前と後ろ DD 以内のところを # で埋めて、最後に . の数をカウントすることで解けました。

ABC468-C

問題ページ: C問題

問題文を表示

問題文

整数 NN(1,2,,N)(1,2,\ldots,N) を並び替えた整数列 P=(P1,P2,,PN),Q=(Q1,Q2,,QN)P=(P_1,P_2,\ldots, P_N),Q=(Q_1,Q_2,\ldots,Q_N) が与えられます。

(1,2,,N)(1,2,\ldots,N) を並び替えた整数列であって辞書順で PP より大きく QQ より小さいものがいくつあるか求めてください。

整数列の辞書順とは?

整数列 S=(S1,S2,,SS)S = (S_1,S_2,\ldots,S_{|S|}) が整数列 T=(T1,T2,,TT)T = (T_1,T_2,\ldots,T_{|T|}) より辞書順で小さいとは、下記の 1. と 2. のどちらかが成り立つことを言います。 ここで、S,T|S|, |T| はそれぞれ S,TS, T の長さを表します。

  1. S<T|S| \lt |T| かつ (S1,S2,,SS)=(T1,T2,,TS)(S_1,S_2,\ldots,S_{|S|}) = (T_1,T_2,\ldots,T_{|S|})
  2. ある整数 1imin{S,T}1 \leq i \leq \min\lbrace |S|, |T| \rbrace が存在して、下記の 22 つがともに成り立つ。
  • (S1,S2,,Si1)=(T1,T2,,Ti1)(S_1,S_2,\ldots,S_{i-1}) = (T_1,T_2,\ldots,T_{i-1})
  • SiS_iTiT_i より(数として)小さい。

制約

  • 1N101\le N\le 10
  • P,QP,Q(1,2,,N)(1,2,\ldots,N) を並び替えた整数列
  • 入力される値は全て整数

入力

入力は以下の形式で標準入力から与えられる。

NN
P1P_1 P2P_2 \ldots PNP_N
Q1Q_1 Q2Q_2 \ldots QNQ_N

出力

答えを出力せよ。

最初に制約が目に入ったときに、これは O(N!)\mathcal{O}(N!) だなと分かりました。

そして、問題を見ると 1N1 \dots N までの整数列の並び替えとあるので、これは順列全列挙だなとなりました。

ここで使えるのが、next_permutation と呼ばれる関数で、数列を辞書順で次の順列に変換させるという関数です。 これを用いることで、数列 PP が数列 QQ と一致するまでループを回し続けその回数をカウントすることで解けました。

C++やPythonでは標準である関数ですが、Javaでは無いので自作する必要があります。

ABC468-D

問題ページ: D問題

問題文を表示

問題文

以下の条件を満たす英小文字からなる文字列を良い文字列とします。

  • 11 文字以下を書き換えることで回文にすることができる。

例えば aiwaiabcdcza などは良い文字列ですが、abcdatcoder などは良い文字列ではありません。特に、回文も良い文字列であることに注意してください。

英小文字からなる文字列 SS が与えられます。

SS の空でない部分文字列(連続な部分列)であって良い文字列であるものの個数を求めてください。

22 つの部分文字列は、SS から取り出す場所が異なれば文字列として等しくても区別して数えることに注意してください。

部分文字列とは

SS部分文字列とは、SS の先頭から 00 文字以上、末尾から 00 文字以上削除して得られる文字列のことをいいます。 例えば、ababc の部分文字列ですが、acabc の部分文字列ではありません。

制約

  • SS は英小文字からなる長さ 11 以上 10410^4 以下の文字列

入力

入力は以下の形式で標準入力から与えられる。

SS

出力

答えを出力せよ。

文字列系の問題でめんどくさそうだなという印象で、問題を読んで2秒でとばしました。 最近はこういった問題を飛ばす判断が結構当たっていて、競技者として本当に強くなってきたなという印象。

E問題を解いた後、約10分で解くことができました。

制約的に NN10410^4 なのでまあ O(N2)\mathcal{O}(N^2) が行けるだろうと思いました。

まず、定数倍速くするのと処理を簡単にするために、最初に Manacher のアルゴリズムを用いて、各点を中心とする最大回文長を偶数長、奇数長ともに求めます。 回文を見つけたらその両端の文字は絶対に異なるので、その文字を書き換えて回文にすることができます。 そこからさらに両端の文字が同じ限り良い文字列なのでそれも忘れないように求めます。

もちろん Manacher を用いずともある点を中心とする良い文字列の最大長を求めるという方法でも解くことができます。

ABC468-E

問題ページ: E問題

問題文を表示

問題文

正整数 NN と長さ NN の整数列 A=(A1,A2,,AN)A=(A_1,A_2,\ldots,A_N) が与えられます。

f(l,r)f(l,r)Al,Al+1,,ArA_l,A_{l+1},\ldots,A_r の(算術)平均として定義します。

1lrNf(l,r)\displaystyle \sum_{1 \le l\le r\le N} f(l,r)mod 998244353\text{mod }{998244353} で求めてください。

有理数 mod 998244353\text{mod }{998244353} の定義

この問題の制約のもとでは、求める有理数を既約分数 PQ\frac{P}{Q} で表した時、Q≢0(mod998244353)Q {{}\not\equiv{}} 0 \pmod{998244353} となることが証明できます。 よって、R×QP(mod998244353),0R<998244353R \times Q \equiv P \pmod{998244353}, 0 \leq R < 998244353 を満たす整数 RR が一意に定まります。 この RR を答えてください。

制約

  • 1N5×1051\le N\le 5\times 10^5
  • 0Ai<9982443530\le A_i \lt 998244353
  • 入力される値は全て整数

入力

入力は以下の形式で標準入力から与えられる。

NN
A1A_1 A2A_2 \ldots ANA_N

出力

答えを出力せよ。

今回ラップタイムで言えば一番時間のかかった問題(約23分)です。 解けたからよかったものの、D問題を飛ばして取り組むにはちょっと重い問題ではありました。

ただ個人的にこういう問題は好きな部類でやることが明確です。 2重ループを回すとTLEになってしまうので、式変形して、前計算や累積和、セグ木とかを用いて1重ループにすればよいだけです。

まず、簡潔に表された数式を元の式に直します。

1lrNf(l,r)=1lrN1rl+1i=lrAi\sum_{1 \le l\le r\le N} f(l,r) = \sum_{1 \le l\le r\le N} \frac{1}{r-l+1} \sum_{i=l}^r A_i

この式に着目すると、まず一番右側のΣは累積和配列を用いることで、 O(1)\mathcal{O}(1) で計算が可能です。 ただし、それだけだとまだ不十分で、 l,rl, r のループに O(N2)\mathcal{O}(N^2) かかってしまいます。

つぎに、 1rl+1\frac{1}{r-l+1} の項に着目すると rrll が異なってもその差が同じであれば、まとめることができます。 つまり、平均を求める区間(項数)を1から順にNまでループしていくことで、区間が同じになる要素の和を O(1)\mathcal{O}(1) で求めることができれば行けそうだなと分かります。

最後に、区間が2の要素の和を考えます。 (A0+A1)+(A1+A2)+...+(AN1+AN)(A_0 + A_1) + (A_1 + A_2) + ... + (A_{N-1} + A_N) であることから。 A0A_0ANA_N つまり、両端の要素だけ1回しか加算されていないことが分かります。この係数部分にだけ着目すると、

A1A2A3A4A5A6A7A8A9111111111122222221123333321123444321123454321\begin{array}{ccccccccc} A_1 & A_2 & A_3 & A_4 & A_5 & A_6 & A_7 & A_8 & A_9 \\ \hline 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\ 1 & 2 & 2 & 2 & 2 & 2 & 2 & 2 & 1 \\ 1 & 2 & 3 & 3 & 3 & 3 & 3 & 2 & 1 \\ 1 & 2 & 3 & 4 & 4 & 4 & 3 & 2 & 1 \\ 1 & 2 & 3 & 4 & 5 & 4 & 3 & 2 & 1 \\ \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots \end{array}

となっていくので、真ん中の部分だけどんどん増やしていくようにすれば区間が同じになる要素の和を O(1)\mathcal{O}(1) で求めることができます。

これは単純に累積和配列のみを用いればよいのですが、遅延セグ木やRangeBITなど、実装を彷徨ってしまったため時間が少しかかってしまいました。

ABC468-F

問題ページ: F問題

問題文を表示

問題文

正整数 NN(1,2,,N)(1,2,\ldots,N) の並び替え P=(P1,P2,,PN)P=(P_1,P_2,\ldots,P_N) が与えられます。

変数 x,y,cx,y,c があります。はじめ x=y=c=0x=y=c=0 です。

あなたは k=1,2,,Nk=1,2,\ldots,N の順に以下の操作のいずれかを行います:

  • 操作 11x<Pkx \lt P_k ならば cc11 増やす。その後、xxmax(x,Pk)\max(x,P_k) に置き換える。
  • 操作 22y<Pky \lt P_k ならば cc11 増やす。その後、yymax(y,Pk)\max(y,P_k) に置き換える。

最終的な cc の値の最大値を求めてください。

制約

  • 1N5×1051\le N\le 5\times 10^5
  • PP(1,2,,N)(1,2,\ldots,N) の並び替え
  • 入力される値は全て整数

入力

入力は以下の形式で標準入力から与えられる。

NN
P1P_1 P2P_2 \ldots PNP_N

出力

答えを出力せよ。

D,Eを順当に解くことができたため、残り1時間近くを残してF問題を始めることができました。

問題は簡単に言うと、2つの操作を行って変数 cc の値を最大化しようというものです。

操作1,2はどちらも同じ操作で対象となる変数が異なるというだけです。それぞれの操作で変数の更新が行えたら cc の値を増やすことができます。

まず単純にこの操作が1だけの時を考えます。この場合は簡単で、前から更新を行っていきその回数が答えになります。 このとき更新を行う際に不要だった要素、つまり変数を更新できなかった要素は一切不要だと分かります。

そこで操作1で更新に不要だった要素を集め、そこでLIS(最長増加部分列)を解くことで、操作2で更新できる回数が分かります。

と、このように案外単純な問題で解くのに約10分しかかかりませんでした。

ABC468-G

問題ページ: G問題

問題文を表示

問題文

整数 NNox からなる長さ NN の文字列 SS が与えられます。

以下の条件を満たす (1,2,,N)(1,2,\ldots,N) の順列 P=(P1,P2,,PN)P=(P_1,P_2,\ldots,P_N) の個数を 998244353998244353 で割ったあまりを求めてください。

  • k=1,2,,Nk=1,2,\ldots,N に対し、以下の 22 つは同値となる。
  • Sk=S_k= o
  • PP(1,2,,k)(1,2,\ldots,k) の順列を連続部分列として含む

制約

  • 1N20001\le N\le 2000
  • SiS_iox からなる長さ NN の文字列

入力

入力は以下の形式で標準入力から与えられる。

NN
SS

出力

答えを出力せよ。

F問題を解いて、約1時間。既にこの時点で黄パフォが出て水色が確実になり速く終わってくれと思いながらこの問題を考えていました。 コンテスト後にACができたので、もっとちゃんとやっていれば奇跡の全完ができたという後悔はありますが、またいつか機会があれば最後まで全力で頑張ろうと思います。

さて、また順列の問題です。ここ最近のG問題の中では550点で青diffだったので、結構簡単目な問題でした。 問題はややこしいですが、要するに Si=S_i = x なら PP1i1 \dots i の順列が連続の部分列として含まれないが、 Sj=S_j = o なら PP1j1 \dots j までの順列が連続の部分列として含まれる、というものです。

まず前提として、 S1=S_1 = x という状況と SN=S_N = x という状況はあり得ないため早期判定を行います。

つぎに oxxoxxo という文字列について考えます。 4文字目に o があるので、141 \dots 4 の順列は含まれます。またこの時点でこの4文字の間には他の数字が入ってはいけないので、ここを一つの塊とみなし、条件を満たす並び方の個数を保持します。 次に5文字目以降を見るとき、前の4文字は1つの塊とみなしたので、この4文字をまとめて o と扱えます。そして次の o までを新たな塊とみなすと、この新しい塊の並び方は、前の塊の並べ方に、前の塊を o とみなした時の並べ方をかけたものになります。 そのように考えると、 o で始まり o で終わる並べ方を長さごとに前列挙しておけば解くことが出来そうです。

この前計算の一般項を求める方法として、小さいケースで next_permutation を用いて全探索を行いその数を求めてOEISで検索し、数列の一般項を特定することで解けます。

oeis.org

最後に

終わってみれば、今回は結構簡単目な回だったのかなと思います。(黄diff以上が無いという意味で)

最近は結構FやGにもチャレンジして精進を行っていたので、その甲斐もあり上振れできたのかなと思います。 上振れ力はあっても圧倒的に演習が不足していてE問題を確実に通せる実力はまだまだなので、すぐに水に落ちそうでひやひやです。 ただ、今回6完という成功体験ができたおかげで今後はFを解くという心理的ハードルを下げられたのかなと思います。

とりあえず、緑に落ちたくないので、また今週も精進します。

← 活動記事一覧に戻る