AtCoder

ABC386 D問題(Diagonal Separation)を解く

AtCoder_ABC386_D

AtCoder が提供しているABC(AtCoder Beginner Contest)386 D問題をC++とPythonで解いてみました。ABC386は、2024年12月28日21:00に実施されました。

AtCoder の紹介はこちらに、プログラミングの方針はこちらに記事があります。

D問題 Diagonal Separation(Difficulty : 996)

問題の詳細は、リンク先をご覧ください。

ABC386 D問題 Diagonal Separation

黒マスが占める最小の領域を特定します。AtCoder Problems による Difficulty は 996 でした。

解答案

C++ プログラム例(ABC386D)

プログラムの補足です。

  • $x$ の範囲が $1 \leqq x \leqq 10^9$ と広いため、座標圧縮を行います(15ー20行目)。
  • 黒マスについて、同じ $x_i$ に対して最大の $y_i$ を求めます。これより $y$ が大きいマスは白マスと見なします(22ー27行目)。
  • 次に、$x$ の値が大きい順に最大の $y$ の値を更新していきます。この操作により、ある $y_i$ に対して、これより $x_i$ が大きいマスは白マスと見なします。具体的な処理は、28行目から35行目のコードを参照してください。
  • 最後に、白マスが黒マスの位置にないかを確認します(37ー44行目)。

以下が、C++プログラムです。

#include <bits/stdc++.h>
using namespace std;

int main()
{
	int n, m;
	cin >> n >> m;
	vector<int> x(m), y(m);
	vector<char> c(m);
	for (int i = 0; i < m; ++i) {
		cin >> x[i] >> y[i] >> c[i];
	}

	// 座標圧縮
	vector<int> nx = x;
	sort(nx.begin(), nx.end());
	nx.erase(unique(nx.begin(), nx.end()), nx.end());
	for (int i = 0; i < m; ++i) {
		x[i] = lower_bound(nx.begin(), nx.end(), x[i]) - nx.begin();
	}

	vector<int> right_b(nx.size(), -1);
	for (int i = 0; i < m; ++i) {
		if (c[i] == 'B') {
			right_b[x[i]] = max(right_b[x[i]], y[i]);
		}
	}
	int right_max = -1;
	for (int i = (int)nx.size() - 1; i >= 0; --i) {
		if (right_b[i] >= right_max) {
			right_max = right_b[i];
		} else {
			right_b[i] = right_max;
		}
	}

	bool result = true;
	for (int i = 0; i < m; ++i) {
		if (c[i] == 'W') {
			if (y[i] <= right_b[x[i]]) {
				result = false;
			}
		}
	}

	if (result) {
		cout << "Yes" << endl;
	} else {
		cout << "No" << endl;
	}

	return 0;
}

AC(Accepted=正しいプログラム)と判定されました。

Python プログラム例(ABC386D)

Python版も基本的な考え方は同じです。座標圧縮の操作はC++版を移植しました(13-15行目)。以下がプログラムです。

"""AtCoder Beginner Contest 386 D"""
import bisect

n, m = map(int, input().split())
x = [0] * m
y = [0] * m
c = [''] * m
for i in range(m):
    tx, ty, c[i] = input().split()
    x[i] = int(tx)
    y[i] = int(ty)

nx = sorted(set(x))
for i in range(m):
    x[i] = bisect.bisect_left(nx, x[i])

right_b = [-1] * len(nx)
for i in range(m):
    if c[i] == 'B':
        right_b[x[i]] = max(right_b[x[i]], y[i])
right_max = -1
for i in range(len(nx) - 1, -1, -1):
    if right_b[i] >= right_max:
        right_max = right_b[i]
    else:
        right_b[i] = right_max

result = True
for i in range(m):
    if c[i] == 'W':
        if x[i] <= y[i] <= right_b[x[i]]:
            result = False

print("Yes" if result else "No")

こちらも「AC」と判定されました。

最後に

このコンテストは私用で参加できませんでした。バーチャル参加しましたが、この問題は1行のコーディングミスにより解けませんでした。惜しい結果でした。

引き続き ABC の問題を紹介していきます。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA