COFO::1671D Insert a Progression

Problem

Point

Design

hard way(tree-way)

solution(easy-way)

Complexity

Code

tree-way

#include<bits/stdc++.h>
#define fi first
#define se second
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
#define rep(i, a, b) for(int i = (a); i <(b); i++)
#define r_rep(i, a, b) for(int i = (a); i >(b); i--)
typedef long long ll;
using namespace std;
const int MAXN = 2 * 1e5 + 9;

int a[MAXN];
map<int,int> mp;
void solve() {
    mp.clear();
    int n, x; cin >> n >> x;
    
    ll ans = 0;
    int mn = MAXN, mx = -MAXN;
    rep(i, 1, n + 1) {
        cin >> a[i];
        mn = min(mn, a[i]);
        mx = max(mx, a[i]);
        if(i != 1) ans += abs(a[i] - a[i-1]);
    }
    int cnt = (int)count(a + 1, a + n + 1, a[1]);
    if (n == 1 || cnt == n) {
        if (1 <= a[1] && a[1] <= x) cout << (x-1) << '\n';
        else if (a[1] > x) cout << (a[1] - 1) << '\n';
        else {
            cout << "Exception1 on 1\n";
        }
        return;
    }
    
    
    int mn_side = min(a[1], a[n]), mx_side = max(a[1], a[n]);
    mp[-MAXN] = 0;
    mp[MAXN] = MAXN;
    mp[1] = x;
    auto check = [](map<int,int>::iterator it, int le, int ri) {
        int st = it->fi, en = it->se;
        if (st == MAXN || st == -MAXN) return;
        if (st <= le && ri <= en) {
            if (st == le) mp.erase(it);
            else it->se = le - 1;
            if (ri < en) mp[ri + 1] = en;
        }
        else if (le <= en && en <= ri) {
            if (st <= le -1) it->se = le - 1;
            else mp.erase(it);
        }
        else if (le <= st && st <= ri) {
            mp.erase(it);
            if (ri < en) mp[ri + 1] = en;
        }
        else if (le <= st && en <= ri) {
            mp.erase(it);
        }
        else {
			// no common area
        }
    };

    rep(i, 1, n) {
        if (a[i] == a[i+1]) continue;
        int le = min(a[i], a[i+1]);
        int ri = max(a[i], a[i+1]);
        auto itLE = --mp.lower_bound(le);
        auto itRI = mp.lower_bound(le);
        
        check(itLE, le, ri);
        check(itRI, le, ri);
    }
    
    for(auto it = mp.begin(); it != mp.end(); it++) {
        int st = it->fi, en = it->se;
        // st < en
        if (st == MAXN || st == -MAXN) continue;
        if (mx <= st) {
            ll len1 = (en - mx) * 2;
            ll len2 = (mx_side <= st ? en - mx_side : mx_side - st);
            ll len3 = (mn_side <= st ? en - mn_side : mn_side - st);
            ans += min(len1, min(len2, len3));
        } else if (en <= mn) {
            ll len1 = (mn - st) * 2;
            ll len2 = (mx_side <= st ? en - mx_side : mx_side - st);
            ll len3 = (mn_side <= st ? en - mn_side : mn_side - st);
            
            ans += min(len1, min(len2, len3));
        } else {
            cout << "Exception3 on for()\n";
        }
    }
    cout << ans << '\n';
}
int main(){
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int tc; cin >> tc; while(tc--)
        solve();
    return 0;
}

best way

#include<bits/stdc++.h>
#define fi first
#define se second
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
#define rep(i, a, b) for(int i = (a); i <(b); i++)
#define r_rep(i, a, b) for(int i = (a); i >(b); i--)
typedef long long ll;
using namespace std;
const int MAXN = 2 * 1e5 + 9;


void solve() {
    int n, Xmax;
    cin >> n >> Xmax;
    vector<int> A(n);
    for(auto &a : A) cin >> a;
    int Amax = *max_element(all(A));
    int Amin = *min_element(all(A));
    
    int Xmin = 1;
    ll ans = 0;
    rep(i, 0, n - 1) ans += abs(A[i+1] - A[i]);
    
    Amax = min(Xmax, Amax);
    
    if (Amax < Xmax) {
        ans += min(
                   2 * (Xmax - Amax),
                   Xmax - max(A.front(), A.back()));
    }
    if (Amin > Xmin) {
        ans += min(
                   2 * (Amin - Xmin),
                   min(A.front(), A.back()) - Xmin);
    }
    cout << ans << '\n';
}
int main(){
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int tc; cin >> tc; while(tc--)
        solve();
    return 0;
}