実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 180
問題概要
数直線上に 匹の蟻がおり、蟻 は始め相異なる座標 にいて正負どちらかの方向を向いている。蟻が向いている向きは0
(負方向) , 1
(正方向) からなる長さ の文字列 で与えられる。現在を時刻 とし、時刻 まで全ての蟻が各々の向いている方向に単位時間あたり の速さで動く。時間 の間に蟻 と がすれ違う整数組 の個数を求めよ。
制約
- は整数。
考察
正方向を向いている蟻に注目し、時間 の間に負方向を向いた蟻と何匹すれ違うかを考えよう。
ここで、単位時間あたりに正方向を向いた蟻と負方向を向いた蟻の距離は 縮まることから、負方向を向いた蟻を数直線上に固定して、正方向を向いた蟻を単位時間あたり の速さで移動させても状況は変わらない。
したがって、正方向を向いた各蟻について、その蟻の位置から正方向に までの範囲内にいる負方向を向いた蟻の数を数えて、それを足し合わせれば答えが求められることになる。
さて、この蟻の数を数えるにあたって、愚直にループを用いると各蟻に対して かかってしまい実行時間制限に間に合わない。そこで、負方向を向いた蟻の位置をソートしておくことで、二分探索により対数時間まで計算量を抑えることができる。
コード
#include <bits/stdc++.h> using namespace std; #define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++) using ll = long long; // ======================================== // int main() { int N, T; cin >> N >> T; string S; cin >> S; vector<ll> left, right; rep(i, 0, N) { ll x; cin >> x; if (S[i] == '0') { left.push_back(x); } else { right.push_back(x); } } sort(all(left)); ll ans = 0; for (auto &&x : right) { ans += upper_bound(all(left), x + 2 * (T + 0.1)) - lower_bound(all(left), x); } cout << ans << endl; }
実装時間: 20分
本当に灰Diffなのかこの問題?