1 条题解
-
0
分类讨论 + 数据结构好题。
以下设 ,,。
首先考虑每次交换两个数的可能方案。这里可以讨论绝对值拆开的情况。
比如说第一种情况,即 , 时(令 为交换的元)。此时的答案偏移量明显为 。其他情况可同理推出。
然后此时就可以用扫描线,即将 当做线段修改, 当做询问。
需要注意的是, 和 的情况需要单独考虑,相邻值交换的影响也可以单独直接计算出。
#include <cmath> #include <vector> #include <cstdio> #include <utility> #include <cstring> #include <iostream> #include <algorithm> #define int long long using namespace std; typedef pair<int, int> pii; #define lc (x << 1) #define rc (x << 1 | 1) #define mpr make_pair #define pb push_back #define px first #define py second const int N = 50005; const int inf = 1e18; int n, ori; int a[N], id[N], rev[N], ans[N], s[N], bl[N], br[N]; vector<pii> vc[N]; namespace sgtree{ struct segtree{ int l, r, mn; #define l(x) tree[x].l #define r(x) tree[x].r #define mn(x) tree[x].mn }; segtree tree[N << 2]; void pushup(int x){mn(x) = min(mn(lc), mn(rc));} void build(int x, int l, int r){ mn(x) = inf; l(x) = l; r(x) = r; if(l == r) return; int mid = (l + r) >> 1; build(lc, l, mid); build(rc, mid + 1, r); pushup(x); } void modify(int x, int p, int val){ if(l(x) == r(x)){mn(x)= val; return;} int mid = (l(x) + r(x)) >> 1; if(p <= mid) modify(lc, p, val); else modify(rc, p, val); pushup(x); } int query(int x, int l, int r){ if(l <= l(x) && r(x) <= r) return mn(x); int mid = (l(x) + r(x)) >> 1; if(r <= mid) return query(lc, l, r); if(l > mid) return query(rc, l, r); return min(query(lc, l, r), query(rc, l, r)); } }; using namespace sgtree; int ask(int p, int l, int r){ int x = bl[p], y = br[p]; if(r == y) -- r; if(r == x) -- r; if(l == x) ++ l; if(l == y) ++ l; if(l > r) return inf; return query(1, l, r); if((x < l && r < y) || r < x || l > y) return query(1, l, r); if(l < x && r > y) return min(query(1, l, x - 1), min(query(1, x + 1, y - 1), query(1, y + 1, r))); if(l < x) return min(query(1, l, x - 1), query(1, x + 1, r)); return min(query(1, l, y - 1), query(1, y + 1, r)); } void solve1(){ for(int i = 1; i <= n; i ++) vc[i].clear(); build(1, 1, n); for(int i = 2; i < n; i ++){ vc[1].pb(mpr(id[i], a[i - 1] + a[i + 1] - 2 * a[i] - s[i])); vc[bl[i]].pb(mpr(id[i], inf)); } for(int i = 1; i <= n; i ++){ for(auto k: vc[i]) modify(1, k.px, k.py); int p = rev[i]; if(p != 1 && p != n) ans[p] = min(ans[p], ask(p, 1, bl[p] - 1) + a[p - 1] + a[p + 1] - 2 * a[p] - s[p]); } } void solve2(){ for(int i = 1; i <= n; i ++) vc[i].clear(); build(1, 1, n); for(int i = 2; i < n; i ++){ vc[bl[i]].pb(mpr(id[i], abs(a[i - 1] - a[i + 1]) - 2 * a[i] - s[i])); vc[br[i]].pb(mpr(id[i], inf)); } for(int i = 1; i <= n; i ++){ for(auto k: vc[i]) modify(1, k.px, k.py); int p = rev[i]; if(p != 1 && p != n){ ans[p] = min(ans[p], ask(p, 1, bl[p] - 1) + a[p - 1] + a[p + 1] - s[p]); } } } void solve3(){ for(int i = 1; i <= n; i ++) vc[i].clear(); build(1, 1, n); for(int i = 2; i < n; i ++) vc[br[i]].pb(mpr(id[i], - 2 * a[i] - a[i - 1] - a[i + 1] - s[i])); for(int i = 1; i <= n; i ++){ for(auto k: vc[i]) modify(1, k.px, k.py); int p = rev[i]; if(p != 1 && p != n) ans[p] = min(ans[p], ask(p, 1, bl[p] - 1) + a[p - 1] + a[p + 1] + 2 * a[p] - s[p]); } } void solve4(){ for(int i = 1; i <= n; i ++) vc[i].clear(); build(1, 1, n); for(int i = 2; i < n; i ++){ vc[1].pb(mpr(id[i], a[i - 1] + a[i + 1] - s[i])); vc[bl[i]].pb(mpr(id[i], inf)); } for(int i = 1; i <= n; i ++){ for(auto k: vc[i]) modify(1, k.px, k.py); int p = rev[i]; if(p != 1 && p != n) ans[p] = min(ans[p], ask(p, bl[p], br[p] - 1) + abs(a[p + 1] - a[p - 1]) - 2 * a[p] - s[p]); } } void solve5(){ for(int i = 1; i <= n; i ++) vc[i].clear(); build(1, 1, n); for(int i = 2; i < n; i ++){ vc[bl[i]].pb(mpr(id[i], abs(a[i + 1] - a[i - 1]) - s[i])); vc[br[i]].pb(mpr(id[i], inf)); } for(int i = 1; i <= n; i ++){ for(auto k: vc[i]) modify(1, k.px, k.py); int p = rev[i]; if(p != 1 && p != n) ans[p] = min(ans[p], ask(p, bl[p], br[p] - 1) + abs(a[p + 1] - a[p - 1]) - s[p]); } } void solve6(){ for(int i = 1; i <= n; i ++) vc[i].clear(); build(1, 1, n); for(int i = 2; i < n; i ++) vc[br[i]].pb(mpr(id[i], - a[i + 1] - a[i - 1] - s[i])); for(int i = 1; i <= n; i ++){ for(auto k: vc[i]) modify(1, k.px, k.py); int p = rev[i]; if(p != 1 && p != n) ans[p] = min(ans[p], ask(p, bl[p], br[p] - 1) + abs(a[p + 1] - a[p - 1]) + 2 * a[p] - s[p]); } } void solve7(){ for(int i = 1; i <= n; i ++) vc[i].clear(); build(1, 1, n); for(int i = 2; i < n; i ++){ vc[1].pb(mpr(id[i], a[i + 1] + a[i - 1] + 2 * a[i] - s[i])); vc[bl[i]].pb(mpr(id[i], inf)); } for(int i = 1; i <= n; i ++){ for(auto k: vc[i]) modify(1, k.px, k.py); int p = rev[i]; if(p != 1 && p != n) ans[p] = min(ans[p], ask(p, br[p], n) - a[p - 1] - a[p + 1] - 2 * a[p] - s[p]); } } void solve8(){ for(int i = 1; i <= n; i ++) vc[i].clear(); build(1, 1, n); for(int i = 2; i < n; i ++){ vc[bl[i]].pb(mpr(id[i], abs(a[i + 1] - a[i - 1]) + 2 * a[i] - s[i])); vc[br[i]].pb(mpr(id[i], inf)); } for(int i = 1; i <= n; i ++){ for(auto k: vc[i]) modify(1, k.px, k.py); int p = rev[i]; if(p != 1 && p != n) ans[p] = min(ans[p], ask(p, br[p], n) - a[p - 1] - a[p + 1] - s[p]); } } void solve9(){ for(int i = 1; i <= n; i ++) vc[i].clear(); build(1, 1, n); for(int i = 2; i < n; i ++) vc[br[i]].pb(mpr(id[i], 2 * a[i] - a[i + 1] - a[i - 1] - s[i])); for(int i = 1; i <= n; i ++){ for(auto k: vc[i]) modify(1, k.px, k.py); int p = rev[i]; if(p != 1 && p != n) ans[p] = min(ans[p], ask(p, br[p], n) + 2 * a[p] - a[p - 1] - a[p + 1] - s[p]); } } int calc(int x, int y){ if(x > y) swap(x, y); int res = 0; if(x != 1) res += abs(a[y] - a[x - 1]) - abs(a[x] - a[x - 1]); if(y != n) res += abs(a[x] - a[y + 1]) - abs(a[y] - a[y + 1]); if(x + 1 != y) res += abs(a[y] - a[x + 1]) + abs(a[x] - a[y - 1]) - abs(a[x + 1] - a[x]) - abs(a[y] - a[y - 1]); return res; } signed main(){ scanf("%lld", &n); for(int i = 1; i <= n; i ++) scanf("%lld", &a[i]), rev[i] = i; for(int i = 2; i <= n; i ++) ori += abs(a[i] - a[i - 1]); sort(rev + 1, rev + n + 1, [](int x, int y){return a[x] < a[y];}); for(int i = 1; i <= n; i ++) id[rev[i]] = i; for(int i = 2; i <= n; i ++) ans[1] = min(ans[1], calc(1, i)); for(int i = 1; i < n; i ++) ans[n] = min(ans[n], calc(i, n)); for(int i = 2; i < n; i ++){ ans[i] = min(ans[i], min(min(calc(1, i), calc(i, n)), min(calc(i, i - 1), calc(i, i + 1)))); s[i] = abs(a[i] - a[i - 1]) + abs(a[i + 1] - a[i]); bl[i] = min(id[i - 1], id[i + 1]); br[i] = max(id[i - 1], id[i + 1]); } solve1(); solve2(); solve3(); solve4(); solve5(); solve6(); solve7(); solve8(); solve9(); for(int i = 1; i <= n; i ++) printf("%lld\n", ori + ans[i]); return 0; }
- 1
信息
- ID
- 2752
- 时间
- 5000ms
- 内存
- 64MiB
- 难度
- 9
- 标签
- 递交数
- 11
- 已通过
- 3
- 上传者