裏紙

ほぼ競プロ、たまに日記

CF 701 E - Connecting Universities

問題

Problem - E - Codeforces

問題概要

頂点数nの木があり、頂点には1からnの番号が振られている(グラフの情報は、各辺がどの頂点を繋いでいるかが与えられる)。このうち、2k個の頂点番号が指定される。それらをu_1 , u_2 , \cdots , u_{2k}とする。これら2k個の頂点から、k個のペアを作る。そのペアの木における距離の総和を最大化するようにペアを作った時、その総和の値を求めよ。

  •  2 \le n \le 200000
  •  1 \le k \le n/2
  •  1 \le u_i \le n

イデア

頂点1を根として考える。すると、DFSによって次の値を各頂点に対して求めることが出来る:

  •  s_i : 頂点iを根とした部分木以下にある指定されている頂点の個数(自分も含む)

最適なペアを取ることの出来る状況を考えてみる。

そこで、頂点vとその親の間にある辺を考えてみると、その辺は min(s_v , 2k - s_v)個のペアのパス上にあることになると言える。これはなぜかというと、まず、これ以上のペアのパス上になることは、この辺を挟んだ位置にあるそれぞれの頂点の個数を考えてみると、物理的に有り得ない。逆にこれ未満である状況を考えると、vを根とする部分木の中にある頂点同士abがペアになっており、その部分木には含まれない頂点同士cdがペアになっているということになる。そして、木の性質上、このペアをacbdに変えることでaからbへのパス上の辺とcからdへのパス上の辺を全てカバーでき、かつパスを長くすることが出来る組み合わせなのでこのような組み合わせは最適ではないことが分かり、上記のことは正しいということが分かった。

ということで、結論は\sum_{i=1}^{n} min(s_i , 2k-s_i )ということになる。

そのようなマッチングを求めることもそんなに改変しなくてもできるよって書いてあるけど、パッとは思いつけない…

実装(C++)

続きを読む

ARC 068 E - Snuke Line

問題

E: Snuke Line - AtCoder Regular Contest 068 | AtCoder

問題概要

M+1個の駅があり、駅に対して0からMまでの番号が振られている。列車は駅0からd駅ごとに停車する。また、N種類の名産品があり、i番目の名産品は駅l_iから駅r_i区間で売られており、その駅に停まると名産品が買える。d=1,2,3, \ldots ,Mの時に買える名産品の個数をそれぞれ求めよ。

  • 1 \le N \le 300000
  • 1 \le M \le 100000
  • 1 \le l_i \le r_i \le M

イデア

まず間隔dを固定して考えてみる。すると、区間の幅(r_i - l_i +1)がdよりも大きい時は、その区間のどこかしらに必ず訪れることになるので、その名産品を買える。一方で、幅がd以下の時はたかだか1回しか訪れることができないのが分かる。

ここで、幅がdより大きい区間については必ず買えるので無視して、幅d以下の区間についてのみ考えると、この区間についてはたかだか1回しか訪れないことがわかっているから区間の累積和を使ってはじめにその位置に含まれる区間の個数を計算してから、dの倍数の位置を調べていけばよいことになる。これでO(N+M)で実現できる。

問題は、d1からMまで動くので、このままでは間に合わない。ただ、幅d以下の区間dを増加させるごとにその数は単調増加になっているので、1からはじめて、上で行った処理をBIT上で行うことで高速に処理することが出来る。

実装(C++)

続きを読む