実行時間制限: 3 sec / メモリ制限: 1024 MB / Difficulty: 735
制約
- 入力はすべて整数。
考察
とりあえず図を書いて考えてみる。

区間について見てみると、この区間上には区間
の始点
が存在する。したがって、区間
と共通部分を持つのは区間
である。
続いて区間について見てみると、この区間上には区間
の始点
が存在する。したがって、区間
と共通部分を持つのは区間
である。
さらに区間について見てみると、この区間上には区間
の始点
が存在する。したがって、区間
と共通部分を持つのは区間
である。
これを一般化して考えてみよう。「区間について、閉区間
上に区間
の始点
が存在するとき、区間
は区間
と共通部分を持つ」と言える。
この考え方をアルゴリズムに落とし込む。
個の区間の始点と終点をペアとしたデータを格納した配列 (
ends
) と、始点のみを格納した配列 (left_pos
) を用意する。なお、両者は昇順ソートされているものとする。ends
を先頭から見ていく。
なお、手順2-1で を求めるには、二分探索 (
upper_bound
) を使うことで高速に求められる。
コード
#include <bits/stdc++.h>usingnamespacestd; #define all(x) (x).begin(), (x).end()#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)using ll = longlong; using Pair_ll = pair<ll, ll>; // ======================================== //intmain() { int N; cin>> N; vector<Pair_ll> ends(N); vector<ll> left_pos; rep(i, 0, N) { ll l, r; cin>> l >> r; ends[i] = make_pair(l, r); left_pos.push_back(l); } sort(all(ends)); sort(all(left_pos)); ll ans = 0; rep(i, 0, N) { ans += (upper_bound(all(left_pos), ends[i].second) - left_pos.begin()) - i - 1; } cout<< ans << endl; }
実装時間: 40分