/ 最近 .rdf 追記 編集 設定 本棚

log[20210616] 競プロ典型 90 問/068 - Paired Information(★5



20210616()

最終更: 2021-06-21T21:06+0900

[AtCoder]競プロ典型 90068 - Paired Information(★5

すごく難しいです。答えの出し方に確証が持てないままとりあえずグラフとして解答を書いたクエリ0に応じて辺を追加するクエリ1に応じてドの値を確定しながら X から Y までグラフをたどるしかし TLE

 提出 #23506723 (TLE×10 / AC×3) ※まだコンテト期間中でありアクセスできないのでこっち>提出 #23506723.rb27

次にクエリ0では Y=X+1 だという制約を思い出してグラフを配列上に配置したしかしこれでは多少効率が良くなれど TLE は解消しない制約はド数(N)クエリ数(Q)ともに上限が 10 万であり1つのクエリに答えるのに線形時間をかけることができない

局所の変更を全体に(対数時間で)波及させるのに BIT がまず浮かぶ何を記録しよう階差の累積値かなと思ったつまり連続する3要素 A,B,C があり2度のクエリ0によって A+B=S, B+C=T であるとわかっているならC-A=T-S から1つおきの2要素の差が直接にわかるこれの累積を記録しておけばクエリ1で XY2×k はなれていても直接計算できる

 提出 #23510943 (AC / 669 Byte / 413 ms / 31888 KB) ※まだアクセスできないのでこっち>提出 #23510943.rb27

結局 BIT は使わなかったクエリへの答え方は階差の累積という点で同じだけどクエリの先読みをすれば事前に累積値が記録しておける更新がないなら値の取得に対数時間がかかる BIT よりただの配列の方が良いAmbiguous と答えるタイミングは Union-Find で管理した

 《上級者向(★7X[i] + 1 = Y[i] の制約を外した場(ワナにとても引っ掛かりやすいです

階差を使う解法は完全Y=X+1 (T=0 の場合)という制約に依存しているのでっかかりを失って困ってしまったグラフなら困らないが TLE階差を封じられてどうすればよい

 A_1A_2……A_{N-1}A_N の関係性がすべて分かっていた場合A_1 の値を +1 すると下図の通り +1 される要素と -1 される要素があります

解説が公開されたプラスかマイナスかそんな単純な関係やったんそれにしてもそこからさらに(厳しくない方の)制約をクリアさせられることがもうつらい

Y=X+1 (T=0 のと) という条件が外れた厳しい方の制約だけどX から Y へ至る異なるパスがクエリ0によって与えられたときにどうすればいいかわからないでいる定数時間で答えるためにどのような情報の持ち方をしておけばいいのか(グラフは TLE)でもプラスかマイナスかという単純な関係なのならばすべてのパスに関わるドをまとめて詰め込んでおいてつじつまが合うのだろう

連結なド間であるドを基準(たとえばゼロ)にして相対的な値を割り振っておくド間の距離(の偶奇)も記録しておく迂回路があっても分岐点・合流点のドが持つ相対値はパスによらず共通だしパスによって異なる非共通ドもド数の偶奇はたぶん同じになるまだよくわからないのは連結成分ごとに基準となるドが必要だけど連結成分同士が連結するたびに基準と相対値のふり直しをして許されるのかというところ小さい方の連結成分を選ぶようにすればいいのだろうけど

全部 Union-Find に乗せたいけどうまくいかないUnite は当然としてFind で集合の代表を書き換えるタイミングでもごにょごにょすると集合の合体があったとしても偶奇と相対値を適切に(新しい代表を基準にして)更新できると思うんだけど符号で死ぬほどバグらせる一見正しい答えに見えてもバグ×バグ=正常だったりする

 https://github.com/monnu123/atcoder_files/blob/master/kyopro90-68.cpp (monnu さん / C++ / 166 ms)

自分がやりたいのはたぶんこういうのっぱりできるんだね不可能をやろうとしてるのでないとわかったのは朗報

ところでRuby のようなスクリト言語と C++ の実行時間が接近しているときは入出力がネックになって C++ の実行時間が遅くなっている印象があるC ランタイムとの連携を切ったりstd::endl が引き起こす flush"\n" で回避したりいろいろ対処法がある模様

 https://github.com/NachiaVivias/kyopro-tenkei-90-submit-nachia/blob/main/shared-solutions/068-Paired-Information/068-01.cpp (Nachia さん / C++ / 51 ms)

っちの見た目すっきりな方はすっきりしすぎてて自分がやりたいことと同じなのかどうかもわからない

ド数が 2N あるなあ前半 N 個と後半 N 個の位置づけとは

偶数世界と奇数世界? これはド番号 X が偶数か奇数かという話ではなく二部グラフの話なのであってあるX を赤色で塗った場合と白色で塗った場合を同時並行で扱っているのではないかという……あてずっぽうです。

 提出 #23560415 (AC / 778 Byte / 334 ms / 16544 KB) ※まだアクセスできないのでこっち>提出 #23560415.rb27

った! うんざりするほどバグらせてついに完成した(UnionFind 全乗せ版)頭が整理されたところでバグまみれを捨ててイチから書き直したのが良かったと思う(それからもバグらせたんだけど)

10
11
	D[a] *= D[g]
	V[a] += D[a]*D[g]*V[g]

↑ここは無駄なことをしてる修正版はこう↓

10
11
	V[a] += D[a]*V[g]
	D[a] *= D[g]

Union-Find でグループの代表とサイズを管理するのはこれまでのおなじみだけど同時に代表からの相対値を記録するのは考えたこともやったこともなかった「重み付き UnionFindというものがあるらしいがったい何に使うものなの

ド数が 2N のすっきり解法は遠くから拝むだけにしておきます。

 https://gist.github.com/masa-aa/4be96f053457dc60625a3552288fb1e4 (masa_aa さん / PyPy3 / 304 ms)

これも重み付き UnionFindド番号の偶奇を利用すれば別途偶奇の管理をする必要がないらしいクエリへの応答部分でだけ偶奇を気にすればいいというのがよくわからないがたぶんこれを考えた先に Nachia さんのサイズ 2N のグラフがあると思う

偶奇を一体でぐちゃぐちゃ扱う(自分)→偶奇に前提をもうけて整理されたグラフを作る(masa_aa さん)→偶奇と奇偶を並行させて偶奇の別を気にしない(Nachia さん)という違いなのではないかという印象を持っている

find メソドで再帰呼び出しをしていないスタックオーバーフローのおそれがないのはいい

これだけの学びがあるのは企画の趣旨に照らして(そうでなくても)すばらしい良問だったのでは?