# Bao Phủ
## Tóm tắt đề bài
Cho một dãy $a$ độ dài $n$ yêu cầu đếm số lượng cặp vị trí $(x, y), x \ne y$ sao cho: $min(|x - y|, |x + y|) \le min(|x|, |y|) \le max(|x|, |y|) \le max(|x - y|, |x + y|)$.
## Lời giải
### SubTask $01$ $(n \le 10^3)$ $\to$ $<O(n^2)>$
Ta đơn giản là duyệt trâu bỏ, xét tất cả các vị trí $(x, y)$ thỏa mãn và đếm.
```c++
for (int i = 1; i <= n; i++)
{
for (int j = i + 1; j <= n; j++)
{
if (i == j) continue;
if (min(abs(a[i] + a[j]),abs(a[i] - a[j])) <= min(abs(a[j]), abs(a[i])) && max(abs(a[j]), abs(a[i])) <= max(abs(a[i] + a[j]), abs(a[i] - a[j])))
{
dem++;
}
}
}
```
### SubTask $02$ $(a_i \ge1 \forall i)$ $\to$ $<O(nlog(n))>$
**Nhận xét**: Ta nhìn vào công thức, khi $a_i \ge 1$ thì $|x - y| \le x$ khi mà $1 \le y \le 2 \times x$ và dĩ nhiêu $|x|, |y| \le |x + y|$.
Ta đưa về bài toán với mỗi $a_i$ ta đếm các giá trị chưa được xét có giá trị không vượt quá $2 \times a_i$. Ta sẽ quy định $a_i$ là giá trị bé hơn, giả sử $u$ là vị trí thỏa mãn $a_u \le 2 \times a_i$ và $u$ là lớn nhất, số cặp ta có thể tìm được với vị trí $i$ là $u - i$.
```c++
sort(a + 1, a + n + 1);
ll res = 0;
for (int i = 1; i <= n; i++)
{
int u = upper_bound(a + 1, a + n + 1, a[i] * 2) - a - 1;
if (a[u] > 2 * a[i]) u--;
if (u > i) res += u - i;
}
cout << res;
```
### SubTask $03$ Không có ràng buộc gì $\to$ $<O(nlog(n))>$
**Nhật xét**: Giả sử, $x \le y$, ta có $2$ trường hợp:
$$
|x - y| \le |y|
\leftrightarrow x^2 - 2xy + y^2 \le y^2
\leftrightarrow x(x - 2y) \le 0
\leftrightarrow \begin{align}
\begin{cases}
x \le 0 \\
x \ge 2y
\end{cases} \\
\begin{cases}
x \ge 0 \\
x \le 2y
\end{cases}
\end{align}
\Rightarrow
\begin{cases}
x \ge 0 \\
x \le 2y
\end{cases} \\
$$
$$
|x + y| \le |y|
\leftrightarrow x^2 + 2xy + y^2 \le y^2
\leftrightarrow x(x + 2y) \le 0
\leftrightarrow \begin{align}
\begin{cases}
x \ge 0 \\
x \le -2y
\end{cases} \\
\begin{cases}
x \le 0 \\
x \ge -2y
\end{cases}
\end{align}
\Rightarrow
\begin{cases}
x \le 0 \\
x \ge -2y
\end{cases} \\
$$
$\Rightarrow \forall x \le y$ để thỏa mãn biểu thức thì $|x| \le |2y|$.
Vậy ta chuyển các giá trị $a_i = |a_i|$ và làm như SubTask $02$.
Có thể sử dụng hai con trỏ:
```c++
sort(a + 1, a + n + 1);
int pos = 1, ans = 0;
for(int i = 1; i <= n; i++){
while(a[pos] <= 2 * a[i] && pos <= n) pos++;
ans += pos - i - 1;
}
```