# CF 1772 D. Absolute Sorting
:::info
[Link](https://codeforces.com/contest/1772/problem/D)
:::
:::spoiler 目錄
[toc]
:::
## 題意
給定一個有$n$個數的數列$a$,請找出一個$x$,使數列$b=[\forall i\in a, \vert i-x\vert]$為一個升序排序的數列。
## 官解
### 思路
對於數列$a$,升序表示$a_1\le a_2\le\cdots \le a_n$,現在假設經過題目的操作後,$x$可以讓$a$被升序排序。
由此可知我們的目標是使關係式$\vert a_i-x\vert\le\vert a_{i+1}-x\vert$成立,這時因為絕對值很難處理,所以要分case解決。
因此將$a_i$和$a_{i+1}$的關係分成以下三種:
1. $a_i=a_{i+1}$
$\vert a_i-x\vert\le\vert a_{i+1}-x\vert\\\Rightarrow \vert a_i-x\vert\le\vert a_i-x\vert$
可以看出$x$不管是多少該式都會成立
2. $a_i<a_{i+1}$
$\vert a_i-x\vert\le\vert a_{i+1}-x\vert$
可以分開考慮$x$的三種範圍是否滿足關係式
1. $x\le a_i$
$$
\vert a_i-x\vert\le\vert a_{i+1}-x\vert\\
\Rightarrow a_i - x\le a_{i+1} - x\\
\Rightarrow a_i\le a_{i + 1}
$$
此範圍滿足
2. $x\ge a_{i+1}$
$$
\vert a_i-x\vert\le\vert a_{i+1}-x\vert\\
\Rightarrow x - a_i\le x - a_{i+1}\\
\Rightarrow a_{i+1}\le a_i
$$
結果與前提矛盾,該式不成立
3. $a_i < x < a_{i + 1}$
$$
\vert a_i-x\vert\le\vert a_{i+1}-x\vert\\
\Rightarrow x-a_i\le a_{i+1}-x\\
\Rightarrow 2x\le a_i+a_{i+1}\\
\Rightarrow x\le \frac{a_i+a_{i+1}}{2}
$$
若$x\le \frac{a_i+a_{i+1}}{2}$,則此範圍滿足
3. $a_i>a_{i+1}$
$\vert a_i-x\vert\le\vert a_{i+1}-x\vert$
可以分開考慮$x$的三種範圍是否滿足關係式
1. $x\le a_{i+1}$
$$
\vert a_i-x\vert\le\vert a_{i+1}-x\vert\\
\Rightarrow a_i-x\le a_{i+1}-x\\
\Rightarrow a_i\le a_{i+1}
$$
結果與前提矛盾,該式不成立
2. $x\ge a_i$
$$
\vert a_i-x\vert\le\vert a_{i+1}-x\vert\\
\Rightarrow x - a_i\le x - a_{i+1}\\
\Rightarrow a_{i+1}\le a_i
$$
此範圍滿足
3. $a_{i+1} < x < a_i$
$$
\vert a_i-x\vert\le\vert a_{i+1}-x\vert\\
\Rightarrow a_i - x\le x - a_{i+1}\\
\Rightarrow 2x\ge a_i+a_{i+1}\\
\Rightarrow x\ge \frac{a_i+a_{i+1}}{2}
$$
若$x\ge \frac{a_i+a_{i+1}}{2}$,則此範圍滿足
所以以結論來說,若$a_i<a_{i+1}$,則$x$必須符合$x\le \frac{a_i+a_{i+1}}{2}$;若$a_i>a_{i+1}$,則$x$必須符合$x\ge \frac{a_i+a_{i+1}}{2}$;若$a_i=a_{i+1}$,則$x$無任何限制。
因為$x$為正整數,所以以上兩個條件等價於:$x\le \lfloor\frac{a_i+a_{i+1}}{2}\rfloor$、$x\ge \lceil\frac{a_i+a_{i+1}}{2}\rceil$
有了以上關係,就只要從頭到尾遍歷$a$一次,解集合即為所有相鄰兩數的$x$範圍的聯集。若集合不存在即為無解。這樣做的時間複雜度為$O{(n)}$。
### code
>> 與初見解基本上一樣,只不過我去除了一些冗句
```cpp=
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
#define F first
#define S second
using namespace std;
const int SIZE = 200050;
int a[SIZE];
void solve() {
int n;
cin >> n;
int prev, now;
pair<int, int> x {0, 1000000000};
cin >> prev;
for (int i = 1; i < n; ++i) {
cin >> now;
if (prev < now) {
x.S = min(x.S, (prev + now) / 2);
} else if (prev > now) {
x.F = max(x.F, (prev + now + 1) / 2);
}
prev = now;
}
if (x.F <= x.S) {
cout << x.F << "\n";
} else {
cout << "-1\n";
}
}
int main() {
ios::sync_with_stdio(0), cin.tie(0);
int t;
cin >> t;
while (t--) {
solve();
}
}
```
## 初見解
### 思路
>> 因為是看題解的,所以思路一樣
### code
```cpp=
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
#define F first
#define S second
using namespace std;
const int SIZE = 200050;
int a[SIZE];
void solve() {
int n;
cin >> n;
int prev, now;
pair<int, int> x {0, 1000000000};
for (int i = 0; i < n; ++i) {
if (!i) {
cin >> prev;
continue;
}
cin >> now;
if (prev < now) {
x.F = max(x.F, 0);
x.S = min(x.S, (prev + now) / 2);
} else if (prev > now) {
x.F = max(x.F, (prev + now + 1) / 2);
x.S = min(x.S, 1000000000);
}
prev = now;
}
if (x.F <= x.S) {
cout << x.F << "\n";
} else {
cout << "-1\n";
}
}
int main() {
ios::sync_with_stdio(0), cin.tie(0);
int t;
cin >> t;
while (t--) {
solve();
}
}
```
###### tags: `每日CF梗題挑戰`