ARC094/ABC093 D問題を解いた

めっちゃ調べて、なるほどって言いながら解いた。
解いた問題はこれ
D - Worst Case
解説がこれ
https://img.atcoder.jp/arc094/editorial.pdf
解説はよくわからなかったので、これ
AtCoder ARC 094 D - Worst Case (700 点) - けんちょんの競プロ精進記録
を参考にして解いた。
これを読むと、元の解説でなんであんなことをしているかも理解できる。

解説

最大となる組み合わせは、1,2,...,xと1,2,...,xという頂点を逆順で組み合わせることで得られることが分かる。
途中に存在するであろうA, Bを飛ばす必要があるため、解答はx-1である。

1, 2, ..., x-1, x
x, x-1, ..., 2, 1

このとき、この最大値は

(x+1)//x * (x+1 - ((x+1)//2))

である。
感覚的に

x//2 * (x - x//2)

だと思っていたので、めっちゃ混乱した。

ここで、B = A + nであるとすると、最大はA*(A+(n-1))以上になることが分かる。
n >= 1であれば、(AとBが異なることに注意すると)積の最大値はA.Bを飛ばしても実現されることが分かる。

A=Bのときはよくわからない。
というわけで、そこは別で扱うことにする。

Q = int( input())
def matching(A,B):
    #最大となる組み合わせは、1,2,...,xと1,2,...,xという頂点を逆順で組み合わせることで得られることが分かる
    #このとき、これらの積の最大値は(x+1)//2*(x+1-(x+1)//2)である
    #ここで、B = A + nであるとき、最大はA*(A+(n-1))以上になることが分かる。
    #n >= 1であれば、積の最大値はA.Bを飛ばしても実現されることが分かる。
    if A == B:
        return 2*A - 2
    S = A*B
    L, H = 0, A*B
    while H - L != 1:
        M = (L+H)//2
        if ((M+1)//2)*(M + 1 - (M+1)//2) < S:
            L = M
        else:
            H = M
    return L-1 #L-1なのは、A,Bを飛ばすため
for _ in range(Q):
    A, B = map( int, input().split())
    print( matching(A,B))