CF1538C Number of Pairs
阿新 • • 發佈:2021-06-13
\(\texttt{Description}\)
給出序列 \(a\) 以及 \(l\) 和 \(r\),求出 \(l\le a_i+a_j\le r\) 且 \(1\le i<j\le n\) 的 \((i,j)\) 數量。
資料範圍:\(1\le n\le2\times10^5,1\le l\le r\le10^9,1\le a_i\le10^9\)
\(\texttt{Solution}\)
-
首先暴力是肯定不行的,所以我們要換一種方法。
-
將序列 \(a\) 從小到大排序。
-
將 \(l\le a_i+a_j\le r\) 這個不等式拆開來看,不妨設 \(i<j\)
-
\(a_j\ge l-a_i\)
-
\(a_j\le r-a_i\)
-
-
所以我們如何確定合法的 \(j\) 的個數呢?自然而然地想到了
lower_bound
與upper_bound
。 -
設對於 \(a_i\) 合法 \(j\) 的左邊界為 \(le\),右邊界為 \(ri\),則:
-
le = lower_bound(a + 1 + i, a + 1 + n, l - a[i]) - a
-
ri = upper_bound(a + 1 + i, a + 1 + n, r - a[i]) - a - 1
-
-
那麼答案就是每個 \(a_i\)
時間複雜度:\(\mathcal{O}(n\log n)\)
\(\texttt{Code}\)
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; int a[200005]; int main () { int T; scanf("%d", &T); while (T--) { int n, l, r; scanf("%d %d %d", &n, &l, &r); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); sort(a + 1, a + 1 + n); ll ans = 0; for (int i = 1; i < n; i++) { int t1 = lower_bound(a + 1 + i, a + 1 + n, l - a[i]) - a; int t2 = upper_bound(a + 1 + i, a + 1 + n, r - a[i]) - a; ans += 1ll * (t2 - t1); } printf("%lld\n", ans); } return 0; }