100,000回:円領域


質問する

  • https://www.acmicpc.net/problem/10000
  • ナビゲーションターゲットをソートし、スタックを介してナビゲーション中に必要な情報
  • のみを保持する.

    きろくてん

  • スタックは、次の繰り返しに必要な情報だけを残します!
    -同時に、次の繰り返しに必要な情報を追加します.
  • 問題を一般化
  • ウォンの包含関係を特定するには、左端座標が必要です.
    したがって、
  • は、幅に基づいて並べ替えられ、その後、関係
  • が含むか否かを決定する.
  • 本人よりも幅の小さい円に含まれる円を見つけ、次の検索範囲で
  • を削除する.
  • の結果、メンバー間に含まれる動作を複数回確認する必要があり、タイムアウト
  • を招く.
  • しかし、円を左端と右端から並べ替えるとは思わなかった.
  • 円を2つの座標に分離して座標に揃えることで、関係を含む
  • を自然に解決することができる.
  • 元を1つのオブジェクトとして残す必要がなく、必要な情報
  • を得ることができる.

    方法

  • 題内容
  • 垂線上に円を配置して、各円の間に包含関係があるかどうかを決定し、
  • .
  • 1 1つの円に含まれる複数の円が満たされているかどうかを確認します.
  • 必要な情報加工
  • を使用
  • ターゲット
  • 垂直線上に円の位置情報
  • が表示する.
  • ウォンの包括関係を確認
  • が互いに含まれていることを確認するには、各円の両端座標が必要です.
    左端
  • ウォン:中点(c)-半径(r)
  • 右端
  • ウォン:中点(c)+半径(r)
  • 円の位置を表示するには、円の両端座標に対して位置合わせする必要があります.
  • 各円の左端、右端の情報は、それぞれ(座標、「L」)、(座標、「R」)
  • と表す.
  • 座標で並べ替える、垂直線上に円を表示する位置
  • .
  • ウォンに含まれている複数の円が、この円を満たしていることを確認します.
  • 元(C)の幅Wは、円に含まれる小円(c 1,c 2,...c n)の幅w 1,w 2,...w nの和と一致すれば、この円は小さな円で満たされていると言える.
  • の場合、c nに含まれる円の幅は、
  • を考慮せずに繰り返す.
  • は、必要に応じて完了した円の情報を提供する必要があります.
  • Lは、Rとの面会時に「完了する円」情報に変換する、考慮すべき情報周期
  • に追加する.
  • [コード構成]
    ステップ
  • 1:円を両端座標値に変換して整列
  • 座標アレイ
  • を作成する
  • 角元です.
  • ウォンのポイント(c)と半径(r)情報確認
  • の左端座標(「L」,c-r)からなり、座標アレイ
  • に追加される
  • 右端座標(「R」,c++r)からなり、座標アレイ
  • に追加する.
  • 座標および左/右情報に基づいてソート
  • 座標昇順に並ぶ
  • 座標相同時に、エラー>左ソート(文字列逆ソート)
  • ステップ
  • ステップ2:座標を順番に参照し、領域をカウントする(スタックに必要な情報のみを残す)
  • スタック
  • を作成
  • 領域数は1
  • に設定.
  • 角座標について
  • 座標属性が左端(L)
  • スタックに追加された
  • 座標属性右端(R)
  • (1つの円が終了するので、スタック内の情報に基づいて生成された領域数を決定する)
  • .
  • スタックの一番後ろの情報(prev)から順にナビゲート
    スタックに
  • prev,pop
  • を配置する
  • prevのプロパティはサブ円(C)です.
  • 子園の幅累計
  • prevの属性は左端(L)
  • (新しい円を作成)
  • サブ円幅の累積和は、新しい円幅に等しい.
  • 子園はすでに満園で、面積2は
  • 増加した.
  • サブ円幅の累積合計は、新しい円幅よりも小さい
  • が満たされていないため、領域数は1
  • 増加する.
  • 新しい円(「C」、幅値)をスタックに追加
  • (次の完成する円に新しい円を含めることができるため、新しい円の幅値は次の繰り返しで考慮される)
  • .
  • スタックナビゲーション終了
  • 回答の提出


    最終的な答え

  • 配列のタプルを配列するときのヒント
    数字
  • 座標(p[1])は昇順、L/R文字(p[0])は降順
  • で、数字p[1]の前に負の値を加算し、逆シーケンスで処理し、
  • 逆パラメータを再びTrueに設定、全体を逆処理
  • に再実行する.
  • (文字p[0]の前に負の値を付けるとタイプエラーになります)
  • コメントリンク
  • import sys
    N = int(sys.stdin.readline())
    
    points = []
    for _ in range(N):
        c, r = list(map(int, sys.stdin.readline().split()))
        points.append(("L", c-r))
        points.append(("R", c+r))
    
    # 좌표 기준 정렬    
    points.sort(key=lambda p: (-p[1], p[0]), reverse=True)
    
    # 차례대로 돌며 확인
    stack = []
    area = 1
    for curr in points:
        # 왼쪽끝인 경우
        if curr[0] == "L":
            stack.append(curr)
            continue
        # 오른쪽끝인 경우
        cum_width = 0
        while stack:
            prev = stack.pop()
            # 본인 내부에 원이 있었으면, 해당 원의 너비를 누적
            if prev[0] == "C":
                cum_width += prev[1]        
            # R이 나올 때마다 L를 pop해주므로 처음 만난 L이 본인과 동일한 원에서 나온 값
            elif prev[0] == "L":
                # 원의 너비 계산
                width = curr[1] - prev[1]
                # 내부에 있는 원들의 너비 합산이 본인의 너비와 일치하는지 확인
                if width == cum_width:
                    area += 2
                else:
                    area += 1
                # 다른 원에 포함될 수 있으므로 추가
                stack.append(("C", width)) 
                break
        
    print(area)