これと似てる!!!
これの解法 3 みたいなやり方をイベントソートって呼ぶのね。
問題概要 (意訳)
くらいのサイズの配列があって最初は INF に初期化されている。 回の以下の操作を行う
- 整数 が与えられて、区間 [ ) 全体を と比較して小さい方で置き換える
このあと、以下の 個のクエリに答えよ
- の位置の値を答えよ。
制約
考えたこと
大体この問題と一緒なので、この問題に対応した 3 つの解法がそれぞれ使える。ここでは解法 3: イベントソートでやってみる。
まさにいもす法の「区間加算」ならぬ「区間 chmin」バージョンという感じ!!!
#include <iostream> #include <vector> #include <set> #include <algorithm> using namespace std; using type = pair<int, long long>; // 1: query, 0; delete, -1: insert using event = pair<long long, type>; int main() { int N, Q; cin >> N >> Q; vector<event> v; for (int i = 0; i < N; ++i) { int s, t, x; cin >> s >> t >> x; v.push_back({s-x, type(-1, x)}); v.push_back({t-x, type(0, x)}); } for (int i = 0; i < Q; ++i) { int d; cin >> d; v.push_back({d, type(1, i)}); } sort(v.begin(), v.end()); vector<long long> res(Q); multiset<long long> se; for (auto p : v) { long long x = p.first; int type = p.second.first; long long val = p.second.second; if (type == -1) se.insert(val); else if (type == 0) se.erase(se.lower_bound(val)); else res[val] = (se.empty() ? -1 : *(se.begin())); } for (auto v : res) cout << v << endl; }