Quantcast
Channel: プログラミング
Viewing all articles
Browse latest Browse all 8151

【AtCoder】ABC 355 D - Intersecting Intervals | 茶コーダーが解くAtCoder - Yuulis.log

$
0
0

atcoder.jp

実行時間制限: 3 sec / メモリ制限: 1024 MB / Difficulty: 735

問題概要

 N個の実数の区間が与えられ、  i番目の区間は閉区間 [l_i, r_i]である。  i番目と  j番目の区間が共通部分を持つような組  (i, j) \: (1 \leq i < j \leq N)の個数を求めよ。

制約

  • 入力はすべて整数。
  •  2 \leq N \leq 5 \times 10^5
  •  0 \leq l_i, r_i \leq 10^9

考察

とりあえず図を書いて考えてみる。



区間 1について見てみると、この区間上には区間 2, 3, 4の始点  l_2, l_3, l_4が存在する。したがって、区間 1と共通部分を持つのは区間 2, 3, 4である。

続いて区間 2について見てみると、この区間上には区間 3, 4の始点  l_3, l_4が存在する。したがって、区間 2と共通部分を持つのは区間 3, 4である。

さらに区間 3について見てみると、この区間上には区間 4, 5の始点  l_4, l_5が存在する。したがって、区間 3と共通部分を持つのは区間 4, 5である。

これを一般化して考えてみよう。「区間 iについて、閉区間 [l_i, r_i]上に区間 jの始点  l_jが存在するとき、区間 j区間 iと共通部分を持つ」と言える。

この考え方をアルゴリズムに落とし込む。

  1.  N個の区間の始点と終点をペアとしたデータを格納した配列 (ends) と、始点のみを格納した配列 (left_pos) を用意する。なお、両者は昇順ソートされているものとする。
  2. endsを先頭から見ていく。
    1. left_posの要素の中で、区間 iの終点  r_iより大きい値が現れるインデックスを  jとする。
    2. 区間 iと共通部分を持つ区間の数は、  j - i - 1で求められる (上図で確認してみよう) 。

なお、手順2-1で  jを求めるには、二分探索 (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;
}

atcoder.jp

実装時間: 40分


Viewing all articles
Browse latest Browse all 8151

Trending Articles