タイトル説明
これは、与えられた数の数字の組と等しいがあるかどうかを尋ねる、整数の数を示します。
入力形式
合計三行:
最初の行は整数である\(N-(0 \ N-LT \ 100000ルは)\) 、表現\(N- \)整数。
2行目は、N個の整数です。範囲内の整数であり、\(0 \)する\(10 ^ 8 \)との間で。
第三のラインは、整数である(LE M \ル2 ^ {30})\ \ M(0)\、および必要性を表明しました。
出力フォーマット
現在、mは出力二つの整数、小さな正面の数であれば、大後、単一のスペースで区切られました。複数の条件の数が満たされている場合、より小さな選択の少ない数の数。数は、出力ライン「NO」の要件を満たすために見つけることができない場合。
サンプル入力
4
2 5 1 4
6
サンプル出力
1 5
トピック分析
この質問は、時間計算量使用することができます\(O(N)\)ダブルポインタ方式のを。(興味のある学生は見つけることができます)
が、我々は説明するためにここに来る\(O(nlogn)\) 2つの分解を。
配列の場合は\(A_1、A_2、...、 A_N \) 、最初の事は、私たちが使用する必要がsort
昇順にそれらを与えるために機能を。
その後、我々はから缶\(1 \)の\(\ N-)横座標\(Iは\) 、のための\([i]が\) 、我々はでき\([I + 1、N ] \) このバイナリ要素と同じであるがあるかどうかを見つけるために、間隔範囲を使用\(ミリアンペア[I]が\) 。
私たちが保証しなければならないとき、もちろん多少、我々は通過\([I] \ルメートル/ 2 \) 私は別の要素のバイナリ検索していますので、その上に、確かにある(\ルA [i]が\)\。
次のようにコードは次のとおりです。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n, m, a[maxn];
// check函数用于二分查找数组a[L,R]中是否存在值为num的元素
bool check(int num, int L, int R) {
while (L <= R) {
int mid = (L + R) / 2;
if (a[mid] == num) return true;
else if (a[mid] > num) R = mid - 1;
else L = mid + 1;
}
return false;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i];
cin >> m;
sort(a+1, a+1+n); // 给数组a[1]到a[n]范围内的数从小到大排序
for (int i = 1; i <= n && a[i] <= m/2; i ++) { // 开始遍历a[i]
if (check(m - a[i], i+1, n)) { // 对[i+1,n]区间范围内二分查找m-a[i]
cout << a[i] << " " << m-a[i] << endl;
return 0;
}
}
puts("NO");
return 0;
}