感觉挺典的,为啥有 2500 啊(
观察发现,反转序列对 \(\sum\limits_{i=1}^{n-1} |a'_i - a'_{i+1}|\) 影响不大。具体而言,设反转了 \(a_l \sim a_r\),记 \(s = \sum\limits_{i=1}^{n-1} |a_i - a_{i+1}|\),那么 \(s' = s - |a_{l-1} - a_l| - |a_r - a_{r+1}| + |a_l - a_{r+1}| + |a_{l-1} - a_r|\)(特判 \(l = 1 \lor r = n\))。
则现在就是要找到一组 \((l,r), 2 \le l \le r < n\),使得 \(s'\) 最小。对后两项拆绝对值之后化成三维偏序的形式,因此跑四遍 cdq 即可。
时间复杂度 \(O(n \log^2 n)\)。cdq 内使用归并排序、树状数组,可以通过。
code
// Problem: E - Pancakes
// Contest: AtCoder - AtCoder Regular Contest 119
// URL: https://atcoder.jp/contests/arc119/tasks/arc119_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 600100;
const ll inf = 0x3f3f3f3f3f3f3f3fLL;
ll n, a[maxn], b[maxn], sum, ans, lsh[maxn], tot, m;
struct node {
ll x, y, z, op;
node(ll a = 0, ll b = 0, ll c = 0, ll d = 0) : x(a), y(b), z(c), op(d) {}
} p[maxn], q[maxn];
inline bool cmp1(const node &a, const node &b) {
if (a.x != b.x) {
return a.x < b.x;
} else if (a.y != b.y) {
return a.y < b.y;
} else if (a.z != b.z) {
return a.z < b.z;
} else {
return a.op < b.op;
}
}
inline bool cmp2(const node &a, const node &b) {
if (a.x != b.x) {
return a.x < b.x;
} else if (a.y != b.y) {
return a.y < b.y;
} else if (a.z != b.z) {
return a.z > b.z;
} else {
return a.op < b.op;
}
}
inline bool cmp3(const node &a, const node &b) {
if (a.x != b.x) {
return a.x < b.x;
} else if (a.y != b.y) {
return a.y > b.y;
} else if (a.z != b.z) {
return a.z < b.z;
} else {
return a.op < b.op;
}
}
inline bool cmp4(const node &a, const node &b) {
if (a.x != b.x) {
return a.x < b.x;
} else if (a.y != b.y) {
return a.y > b.y;
} else if (a.z != b.z) {
return a.z > b.z;
} else {
return a.op < b.op;
}
}
namespace BIT {
ll c[maxn];
inline void init() {
mems(c, 0x3f);
}
inline void clear(int x) {
for (int i = x; i <= tot; i += (i & (-i))) {
c[i] = inf;
}
}
inline void update(int x, ll d) {
for (int i = x; i <= tot; i += (i & (-i))) {
c[i] = min(c[i], d);
}
}
inline ll query(int x) {
ll res = inf;
for (int i = x; i; i -= (i & (-i))) {
res = min(res, c[i]);
}
return res;
}
}
void cdq1(int l, int r) {
if (l >= r) {
return;
}
int mid = (l + r) >> 1, i = l, j = mid + 1, t = 0;
cdq1(l, mid);
cdq1(mid + 1, r);
while (i <= mid && j <= r) {
if (p[i].y <= p[j].y) {
if (p[i].op == 1) {
BIT::update(p[i].z, -b[p[i].x - 1] - a[p[i].x] - a[p[i].x - 1]);
}
q[++t] = p[i++];
} else {
if (p[j].op == 2) {
ans = min(ans, sum + BIT::query(p[j].z) - b[p[j].x] + a[p[j].x + 1] + a[p[j].x]);
}
q[++t] = p[j++];
}
}
while (i <= mid) {
if (p[i].op == 1) {
BIT::update(p[i].z, -b[p[i].x - 1] - a[p[i].x] - a[p[i].x - 1]);
}
q[++t] = p[i++];
}
while (j <= r) {
if (p[j].op == 2) {
ans = min(ans, sum + BIT::query(p[j].z) - b[p[j].x] + a[p[j].x + 1] + a[p[j].x]);
}
q[++t] = p[j++];
}
for (int i = l; i <= mid; ++i) {
if (p[i].op == 1) {
BIT::clear(p[i].z);
}
}
for (int i = 1; i <= t; ++i) {
p[l + i - 1] = q[i];
}
}
void cdq2(int l, int r) {
if (l >= r) {
return;
}
int mid = (l + r) >> 1, i = l, j = mid + 1, t = 0;
cdq2(l, mid);
cdq2(mid + 1, r);
while (i <= mid && j <= r) {
if (p[i].y <= p[j].y) {
if (p[i].op == 1) {
BIT::update(tot - p[i].z + 1, -b[p[i].x - 1] - a[p[i].x] + a[p[i].x - 1]);
}
q[++t] = p[i++];
} else {
if (p[j].op == 2) {
ans = min(ans, sum + BIT::query(tot - p[j].z + 1) - b[p[j].x] + a[p[j].x + 1] - a[p[j].x]);
}
q[++t] = p[j++];
}
}
while (i <= mid) {
if (p[i].op == 1) {
BIT::update(tot - p[i].z + 1, -b[p[i].x - 1] - a[p[i].x] + a[p[i].x - 1]);
}
q[++t] = p[i++];
}
while (j <= r) {
if (p[j].op == 2) {
ans = min(ans, sum + BIT::query(tot - p[j].z + 1) - b[p[j].x] + a[p[j].x + 1] - a[p[j].x]);
}
q[++t] = p[j++];
}
for (int i = l; i <= mid; ++i) {
if (p[i].op == 1) {
BIT::clear(tot - p[i].z + 1);
}
}
for (int i = 1; i <= t; ++i) {
p[l + i - 1] = q[i];
}
}
void cdq3(int l, int r) {
if (l >= r) {
return;
}
int mid = (l + r) >> 1, i = l, j = mid + 1, t = 0;
cdq3(l, mid);
cdq3(mid + 1, r);
while (i <= mid && j <= r) {
if (p[i].y >= p[j].y) {
if (p[i].op == 1) {
BIT::update(p[i].z, -b[p[i].x - 1] + a[p[i].x] - a[p[i].x - 1]);
}
q[++t] = p[i++];
} else {
if (p[j].op == 2) {
ans = min(ans, sum + BIT::query(p[j].z) - b[p[j].x] - a[p[j].x + 1] + a[p[j].x]);
}
q[++t] = p[j++];
}
}
while (i <= mid) {
if (p[i].op == 1) {
BIT::update(p[i].z, -b[p[i].x - 1] + a[p[i].x] - a[p[i].x - 1]);
}
q[++t] = p[i++];
}
while (j <= r) {
if (p[j].op == 2) {
ans = min(ans, sum + BIT::query(p[j].z) - b[p[j].x] - a[p[j].x + 1] + a[p[j].x]);
}
q[++t] = p[j++];
}
for (int i = l; i <= mid; ++i) {
if (p[i].op == 1) {
BIT::clear(p[i].z);
}
}
for (int i = 1; i <= t; ++i) {
p[l + i - 1] = q[i];
}
}
void cdq4(int l, int r) {
if (l >= r) {
return;
}
int mid = (l + r) >> 1, i = l, j = mid + 1, t = 0;
cdq4(l, mid);
cdq4(mid + 1, r);
while (i <= mid && j <= r) {
if (p[i].y >= p[j].y) {
if (p[i].op == 1) {
BIT::update(tot - p[i].z + 1, -b[p[i].x - 1] + a[p[i].x] + a[p[i].x - 1]);
}
q[++t] = p[i++];
} else {
if (p[j].op == 2) {
ans = min(ans, sum + BIT::query(tot - p[j].z + 1) - b[p[j].x] - a[p[j].x + 1] - a[p[j].x]);
}
q[++t] = p[j++];
}
}
while (i <= mid) {
if (p[i].op == 1) {
BIT::update(tot - p[i].z + 1, -b[p[i].x - 1] + a[p[i].x] + a[p[i].x - 1]);
}
q[++t] = p[i++];
}
while (j <= r) {
if (p[j].op == 2) {
ans = min(ans, sum + BIT::query(tot - p[j].z + 1) - b[p[j].x] - a[p[j].x + 1] - a[p[j].x]);
}
q[++t] = p[j++];
}
for (int i = l; i <= mid; ++i) {
if (p[i].op == 1) {
BIT::clear(tot - p[i].z + 1);
}
}
for (int i = 1; i <= t; ++i) {
p[l + i - 1] = q[i];
}
}
void solve() {
scanf("%lld", &n);
for (int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
}
for (int i = 1; i < n; ++i) {
b[i] = abs(a[i] - a[i + 1]);
sum += b[i];
}
ans = sum;
for (int i = 2; i < n; ++i) {
ans = min(ans, sum - b[i] + abs(a[1] - a[i + 1]));
}
for (int i = n - 1; i >= 2; --i) {
ans = min(ans, sum - b[i - 1] + abs(a[n] - a[i - 1]));
}
for (int i = 1; i <= n; ++i) {
lsh[++tot] = a[i];
}
sort(lsh + 1, lsh + tot + 1);
tot = unique(lsh + 1, lsh + tot + 1) - lsh - 1;
for (int i = 2; i < n; ++i) {
int x = lower_bound(lsh + 1, lsh + tot + 1, a[i - 1]) - lsh;
p[++m] = node(i, a[i], x, 1);
}
for (int i = 2; i < n; ++i) {
int x = lower_bound(lsh + 1, lsh + tot + 1, a[i]) - lsh;
p[++m] = node(i, a[i + 1], x, 2);
}
BIT::init();
sort(p + 1, p + m + 1, cmp1);
cdq1(1, m);
sort(p + 1, p + m + 1, cmp2);
cdq2(1, m);
sort(p + 1, p + m + 1, cmp3);
cdq3(1, m);
sort(p + 1, p + m + 1, cmp4);
cdq4(1, m);
printf("%lld\n", ans);
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}