Bondo416さんのAtCoder Beginner Contest 294での成績:297位
— ボンド@競プロ (@bond_cmprog) March 19, 2023
パフォーマンス:1983相当
レーティング:1520→1575 (+55) :)#AtCoder #ABC294 https://t.co/VkPOH2uinE
A - Filter
偶数の入力のみ出力
void solve() { int N; cin >> N; REP(i, N) { int a; cin >> a; if (a % 2 == 0) cout << a << " "; } cout << endl; }
B - ASCII Art
問題文のとおりに数値を文字列に変換する
void solve() { int H, W; cin >> H >> W; REP(i, H) { REP(j, W) { int a; cin >> a; if (a == 0) cout << "."; else cout << char('A' + a - 1); } cout << endl; } }
C - Merge Sequences
座圧と同じ操作をする
$ C_k = A_i $、$ C_k = B_j $ を満たす $ k $ を二分探索で求める
void solve() { int N, M; cin >> N >> M; vector<int> A(N), B(M); vector<int> C; REP(i, N) { cin >> A[i]; C.emplace_back(A[i]); } REP(i, M) { cin >> B[i]; C.emplace_back(B[i]); } sort(ALL(C)); REP(i, N) { int idx = lower_bound(ALL(C), A[i]) - C.begin(); cout << idx + 1 << " "; } cout << endl; REP(i, M) { int idx = lower_bound(ALL(C), B[i]) - C.begin(); cout << idx + 1 << " "; } cout << endl; }
D - Bank
まだ呼ばれていない番号の集合とすでに受付に呼ばれているが受付に行っていない人の集合それぞれをsetで管理をする
void solve() { int N, Q; cin >> N >> Q; set<int> st1, st2; REP(i, N) st1.emplace(i); while (Q--) { int q; cin >> q; if (q == 1) { int x = *st1.begin(); st1.erase(x); st2.emplace(x); } else if (q == 2) { int x; cin >> x; st2.erase(x - 1); } else { cout << *st2.begin() + 1 << endl; } } }
E - 2xN Grid
要素ごとにRangeSetで区間を管理する
予め $ A $ の要素を区間に追加しておく
その後 $ B $ の要素を区間に追加する
$ [l, r) $ の区間を追加したときに追加される区間の増分を $ x $ とすると、その区間には元々 $ r - l - x $ 個の要素があるのでこの総和を求めればいい
void solve() { ll L, N1, N2; cin >> L >> N1 >> N2; map<ll, vector<pair<ll, ll>>> mp1, mp2; ll sum = 0; REP(i, N1) { ll v, l; cin >> v >> l; mp1[v].emplace_back(sum, sum + l); sum += l; } sum = 0; REP(i, N2) { ll v, l; cin >> v >> l; mp2[v].emplace_back(sum, sum + l); sum += l; } ll ans = 0; for (auto [k, v] : mp1) { RangeSet<ll> rst; for (auto [l, r] : v) { rst.insert(l, r); } if (mp2.count(k)) { for (auto [l, r] : mp2[k]) { ll x = rst.insert(l, r); ans += r - l - x; } } } cout << ans << endl; }
G - Distance Queries on a Tree
クエリが木上のパスではなく、列であったとすると、1点変更、区間加算ができるセグ木を使用することで求めることができる
木に対してはHL分解を行うことで列と同様にできるのでこれをセグ木を使って求めればいい
void solve() { int N; cin >> N; vector<int> v(N - 1), u(N - 1), w(N - 1); HLD hld(N); REP(i, N - 1) { cin >> v[i] >> u[i] >> w[i]; --v[i], --u[i]; hld.add_edge(v[i], u[i]); } hld.build(); SegTree<ll> seg( N, [](ll a, ll b) { return a + b; }, 0); REP(i, N - 1) { seg.set(max(hld.vid[v[i]], hld.vid[u[i]]), w[i]); } seg.build(); int Q; cin >> Q; while (Q--) { int q; cin >> q; if (q == 1) { int i; ll w; cin >> i >> w; --i; seg.update(max(hld.vid[v[i]], hld.vid[u[i]]), w); } else { int uu, vv; cin >> uu >> vv; --uu, --vv; if (uu > vv) swap(uu, vv); ll sum = 0; for (auto [l, r] : hld.for_each_edge(uu, vv)) { sum += seg.get(l, r); } cout << sum << endl; } } }