题解:CF2081B Balancing
题意:
称「下降数
引理 1:
显然。
引理 2:一次操作最多将
操作
(l,r) 只有可能删掉l-1,r 两个下降点。
推论 1:答案的下界为
引理 3:当
如图:
引理 4:如果每次操作都让
如果想让他动,因为他是最左边的,再左边没有下降点了,
d 也就减不了2 了。
引理 5:当
如图:
推论 2:
推论 3:
引理 6:当
如图:
推论 4:此时答案为
推论 5:
引理 7:当
里面全是上升,最理想情况压到全
+1 。此时左右两点平均斜率至少为1 ,矛盾,因此一次操作压不进去。两次操作很简单,左边点一按,右边点一抬就 ok 了。
引理 8:符合引理 7 所述情况但
等价于
\frac d2 是不行的。如果一直按引理 2 的方法调整,那么根据引理 4,最后肯定面临一个引理 7 的情况。
推论 6:此情况下答案为
结合引理 1,推论 3,推论 5,推论 6 可得出答案。
#include <bits/stdc++.h>
using namespace std;
namespace heead {
// types
using i32 = int32_t;
using i64 = int64_t;
using i128 = __int128;
using f32 = float;
using f64 = double;
using f128 = __float128;
using ll = long long;
using ldb = long double;
#define umap unordered_map
#define uset unordered_set
#define prque priority_queue
#define pi32 pair<i32, i32>
#define pi64 pair<i64, i64>
#define pll pair<ll, ll>
// functions
#define emp emplace
#define empb emplace_back
#define empf emplace_front
#define mkp make_pair
mt19937_64 rd(chrono::high_resolution_clock().now().time_since_epoch().count());
// constants
#define csep constexpr
csep i64 inf = 0x3f3f3f3f3f3f3f3fll;
csep f64 eps = 1e-7;
csep f64 PI = 3.14159265358979323846264338327950288419716939937510582097;
// non-std type io
istream& operator>>(istream& in, i128& x) {
string input;
in >> input;
x = 0;
for (char c : input) {
if (c == '-') {
continue;
}
x = (x << 3) + (x << 1) + (c & 15);
}
if (input[0] == '-') {
x *= -1;
}
return in;
}
ostream& operator<<(ostream& out, i128 x) {
stack<char> output;
if (x < 0) {
out << '-';
x *= -1;
}
if (!x) {
out << '0';
return out;
}
while (x) {
output.emp((x % 10) | 48);
x /= 10;
}
while (!output.empty()) {
out << output.top();
output.pop();
}
return out;
}
istream& operator>>(istream& in, f128& x) {
string input;
in >> input;
f128 mul = 1;
i64 id = (input.find('.') == string::npos ? input.length() : input.find('.')) - (input[0] == '-') - 1;
for (ll i = 1; i <= id; ++i) {
mul *= 10;
}
x = 0;
for (char c : input) {
if (c == '.' || c == '-') {
continue;
}
x += mul * (c & 15);
mul /= 10;
}
if (input[0] == '-') {
x *= -1;
}
return in;
}
csep i64 F128ACC = 12;
ostream& operator<<(ostream& out, f128 x) {
// negative case
if (x < 0) {
out << '-';
x *= -1;
}
// integer part
out << i128(x);
x -= i128(x);
// fractional part
for (ll i = 1; i <= F128ACC; ++i) {
x *= 10;
}
if (!x) {
return out;
}
out << '.';
// prefix 0
i128 y = x;
i128 _y = y;
for (ll i = 1; i <= F128ACC; ++i) {
if (!_y) {
out << '0';
}
_y /= 10;
}
// suffix 0
while (y && y % 10 == 0) {
y /= 10;
}
// out
out << i128(y);
return out;
}
}
using namespace heead;
ll n, a[1000005];
vector<pll> inv;
void init() {
fill_n(a, n + 4, inf);
inv.clear();
}
int mian() {
cin >> n;
a[n + 1] = inf;
for (ll i = 1; i <= n; ++i) cin >> a[i];
ll l = 1, ans = 0;
for (ll i = 2; i <= n; ++i) {
if (a[i - 1] > a[i]) {
inv.empb(mkp(i - 1, i));
}
}
if (inv.size() <= 1) {
cout << inv.size() << endl;
return 0;
}
if (inv.size() % 2) {
cout << inv.size() / 2 + 1 << endl;
} else {
if (inv.back().second - inv[0].first <= a[inv.back().second] - a[inv[0].first]) {
cout << inv.size() / 2 << endl;
} else {
cout << inv.size() / 2 + 1 << endl;
}
}
return 0;
}
#define FASTIO
int main() {
#ifdef FASTIO
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#endif
i32 T;
cin >> T;
while (T--) init(), mian(), init();
return 0;
}