コドフォ Educational Contest 92 D Segment Intersections 解説[python]
概要
区間[l1,r1],[l2,r2] のがそれぞれN 本ある。
i 番目の[l1,r1]区間はi 番目の[l2,r2]区間と対応する。
任意の区間の距離を長さ1伸ばすのにstepが1かかる。(左右両方向に伸ばせる)
それぞれの対応する区間同士が重なっている長さの合計をk以上にするのにかかる最低のstep数を答えよ。
制約
n <= 2*10**5
1<= l,r,k <=10**9
考察
性質として、現在重なっていて、対応する区間同士にまだ重なっていない部分があるなら、そこを使い切るまでコスト1で長さを1伸ばせる。
使い切っているならば、現在重なっていない区間をgapを埋めて使い切るか(選択1)
、現在重なっている区間に関して、両方の端を伸ばして、コスト2で長さを1伸ばすか(選択2)
の2つの選択肢がある。
選択2の時、gap分だけコストがかかるので、解を決めうつと条件分岐が少なく実装が楽になる。
場合わけとして
実装
import sys import math read = sys.stdin.buffer.read # input = sys.stdin.buffer.readline readlines = sys.stdin.buffer.readlines t = int(input()) for case in range(t): n, k = map(int, input().split()) l1, r1 = map(int, input().split()) l2, r2 = map(int, input().split()) origin_inter = max(0, min(r1, r2) - max(l1, l2)) ans = 0 k -= origin_inter * n if k <= 0: ans = 0 elif origin_inter > 0: # まず伸ばせるまで伸ばす。その後、2ターンで1伸ばす if k <= n * ((r1 - l1) + (r2 - l2) - origin_inter * 2): ans += k else: ans = 2 * k - n * ((r1 - l1) + (r2 - l2) - origin_inter * 2) else: margin = max(l1, l2) - min(r1, r2) len_inter = max(r1, r2) - min(l1, l2) # 何本を使うかを決め打つ ans = 10 ** 10 for i in range(1, n + 1): tmp_i = margin * i if k > len_inter * i: tmp_i += len_inter * i + (k - len_inter * i) * 2 else: tmp_i += k # print(i, tmp_i, margin, len_inter) ans = min(tmp_i, ans) print(ans)