AtCoder

ABC343 F問題(Second Largest Query)を解く

AtCoder_ABC343_F

AtCoder が提供しているABC(AtCoder Beginner Contest)343 のF問題をC++で解いてみました。ABC343は、2024年3月2日21:00に実施されました。

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

F問題 Second Largest Query(Difficulty : 1370)

問題はリンク先をご覧ください。

ABC343 F問題 Second Largest Query

一番大きい値とその個数、二番目に大きい値とその個数をセグメント木で管理します。AtCoder Problems による Difficulty は 1370 でした。

解答案

セグメント木を使います。

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

型は、一番大きい値とその個数、二番目に大きい値をメンバに持つ構造体とします(7ー12行目)。演算する関数 op、単位元を返す関数 e を以下のように定義します。

  • 関数 op:二つの構造体から、一番大きい値とその個数、二番目に大きい値を計算します。map コンテナを使って値を求めました(14ー32行目)。
  • 関数 e:{-1, 0, -2, 0} を返します(34ー37行目)。

以下が、C++プログラムとなります。セグメント木の操作に関するコードの背景色を変更しています。

#include <bits/stdc++.h>
#include <atcoder/segtree>

using namespace std;
using namespace atcoder;

typedef struct {
	int fv; // first value
	int fc; // first count
	int sv; // second value
	int sc; // second count
} S;

S op(S a, S b)
{
	S result;

	map<int, int> m;
	m[a.fv] += a.fc;
	m[a.sv] += a.sc;
	m[b.fv] += b.fc;
	m[b.sv] += b.sc;

	auto it = m.rbegin();
	result.fv = (*it).first;
	result.fc = (*it).second;
	++it;
	result.sv = (*it).first;
	result.sc = (*it).second;

	return result;
}

S e()
{
	return (S){-1, 0, -2, 0};
}

int main()
{
	int n, q;
	cin >> n >> q;
	vector<int> a(n);
	for (int i = 0; i < n; ++i) {
		cin >> a[i];
	}

	segtree<S, op, e> seg(n);
	for (int i = 0; i < n; ++i) {
		seg.set(i, (S){a[i], 1, -1, 0});
	}

	for (int i = 0; i < q; ++i) {
		int type;
		cin >> type;
		if (type == 1) {
			int p, x;
			cin >> p >> x;
			--p;
			seg.set(p, (S){x, 1, -1, 0});
		} else if (type == 2) {
			int L, R;
			cin >> L >> R;
			--L;
			S result = seg.prod(L, R);
			cout << result.sc << endl;
		}
	}

	return 0;
}

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

Python のセグメント木について

Python は、セグメント木を標準ライブラリとしては用意していません。このブログの Python プログラムは、なるべく言語標準のライブラリで実装したいと考えています。このような事情で、この記事では、Python に移植したプログラムの紹介を省略します。

最後に

型を工夫してセグメント木を使う問題でした。セグメント木を使う問題に慣れていければと思います。

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

COMMENT

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

CAPTCHA