配点: 300 点 / 実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 209
問題概要
から
までの番号が付いた
匹の鳩と、
から
までの番号が付いた
個の巣がある。はじめ、鳩
は巣
にいる。
個のクエリが与えられるので順に処理せよ。クエリは2種類あり、以下のいずれかの形式で与えられる。
1 P H: 鳩を巣
に移動させる。
2: 複数の鳩がいる巣の個数を出力する。
制約
- 1つ目のクエリについて、鳩
は移動する前に巣
にいない。
- 入力は全て整数。
考察
とりあえず、現在鳩がどの巣にいるのかを管理したいので、そのための配列pigeonsを用意する。
また、巣に何匹の鳩がいるのかも知りたいので、そのための配列homesを用意する。
鳩
が現在いる巣の番号
巣
に現在いる鳩の数
こうすることで、クエリ1は以下のように書ける。
homes[pigeons[P]]--; // 鳩 P が今いる巣を離れる homes[H]++; // 鳩 P が巣 H に移動 pigeons[P] = H; // 鳩の位置も更新
クエリ2では となる
の個数を数えたいが、このために毎回
forループを回していると TLE してしまう。
そこで、この個数自体を予め変数に持っておくことにする(ここではcntとした)。
cntが更新されるのは以下のタイミングとなる。
となったとき、
となったとき、
あとは、クエリ2ではcntを出力すればよいだけ。
結局、どちらのクエリも で処理できることになった。
実装例では 0-indexed になっていることに注意。
実装例
#include <bits/stdc++.h> using namespace std; #define all(x) (x).begin(), (x).end() // ======================================== // int main() { int N, Q; cin >> N >> Q; int cnt = 0; vector<int> pigeons(N), homes(N, 1); iota(all(pigeons), 0); while (Q--) { int t; cin >> t; if (t == 1) { int P, H; cin >> P >> H; P--; H--; homes[pigeons[P]]--; if (homes[pigeons[P]] == 1) cnt--; homes[H]++; if (homes[H] == 2) cnt++; pigeons[P] = H; } else if (t == 2) { cout << cnt << endl; } } return 0; }
実装時間: 10分
コメント
特別なデータ構造が必要になるかと身構えていたが、案外vectorだけでもなんとかなって拍子抜け。