1 条题解

  • 0
    @ 2026-9-26 20:36:15

    分类讨论 + 数据结构好题。

    以下设 si=∣ai−ai−1∣+∣ai−ai+1∣s_i =|a_i - a_{i-1}|+|a_i-a_{i+1}|,li=min⁡(ai−1,ai+1)l_i = \min(a_{i-1},a_{i+1}),ri=max⁡(ai−1,ai+1)r_i = \max(a_{i-1},a_{i+1})。

    首先考虑每次交换两个数的可能方案。这里可以讨论绝对值拆开的情况。

    比如说第一种情况,即 ai<lj<rja_i < l_j < r_j,aj<ri<lia_j<r_i<l_i 时(令 i,ji,j 为交换的元)。此时的答案偏移量明显为 lj+rj−2ai+li+ri−2aj−si−sjl_j+r_j-2a_i+l_i+r_i-2a_j-s_i-s_j。其他情况可同理推出。

    然后此时就可以用扫描线,即将 jj 当做线段修改,ii 当做询问。

    需要注意的是,11 和 nn 的情况需要单独考虑,相邻值交换的影响也可以单独直接计算出。

    #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
    上传者