Source Code
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<ll, int> pll;

#define sim template <class c
#define ris return *this
#define dor > debug& operator<<
#define eni(x) sim > typename enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) {
    return rge<c>{i, j};
}
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
    ~debug() {
        cerr << endl;
    }
    eni(!=) cerr << boolalpha << i;
    ris;
} eni(==) ris << range(begin(i), end(i));
}
sim, class b dor(pair<b, c> d) {
    ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
    *this << "[";
    for (auto it = d.b; it != d.e; ++it)
        *this << ", " + 2 * (it == d.b) << *it;
    ris << "]";
}
#else
    sim dor(const c&) {
        ris;
    }
#endif
}
;
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

const ll INF = 1e18;
const ll INF2 = 1e15;

const int N = 100100;

struct Segment {
    ll value, offset;
    int i;

    Segment(ll value = INF, ll offset = INF, int i = -1) : value(value), offset(offset), i(i) {
    }

    bool operator<(const Segment& other) const {
        return value + offset < other.value + other.offset;
    }

    void Debug() {
        debug() << imie(value) imie(offset) imie(i);
    }
};

struct SegmentTreeLazy {
#define Mid ((L + R) >> 1)
#define Left (Node << 1)
#define Right (Node << 1 | 1)

   private:
    const ll EL = INF;             /// identity element for lazy   /// Check this
    static const int Nax = 4 * N;  /// Check this

    int n;  /// Array length
    Segment Tree1[Nax];
    Segment Tree2[Nax];
    ll Lazy[Nax];

   public:
    SegmentTreeLazy(int n = 0) : n(n) {
        for (int Node = 0; Node < Nax; Node++) {
            Tree1[Node] = Segment();
            Tree2[Node] = Segment(0);
            Lazy[Node] = EL;
        }
    }

   private:
    Segment Unite(Segment x, Segment y) {  /// Check this
        return min(x, y);
    }

   private:
    void Merge(int Node) {
        Tree1[Node] = Unite(Tree1[Left], Tree1[Right]);
        Tree2[Node] = Unite(Tree2[Left], Tree2[Right]);
    }

   private:
    void PushLazy(int Node, int Len) {
        if (Lazy[Node] != EL) {
            if (Tree1[Node].value + Tree1[Node].offset > Lazy[Node] + Tree2[Node].offset) {
                Tree1[Node].value = Lazy[Node];
                Tree1[Node].offset = Tree2[Node].offset;
                Tree1[Node].i = Tree2[Node].i;
            }
            if (Len > 1) {
                Lazy[Left] = min(Lazy[Left], Lazy[Node]);    /// Check this
                Lazy[Right] = min(Lazy[Right], Lazy[Node]);  /// Check this
            }
            Lazy[Node] = EL;
        }
    }

   public:
    void Build(const vector<ll>& a) {
        Clear();
        n = a.size();
        Build(a, 1, 0, n - 1);
    }

   private:
    void Build(const vector<ll>& a, int Node, int L, int R) {
        Tree1[Node] = Segment();
        Tree2[Node] = Segment(0);
        Lazy[Node] = EL;
        if (L == R) {
            Tree1[Node] = Segment(INF, a[L], L);
            Tree2[Node] = Segment(0, a[L], L);
            return;
        }
        Build(a, Left, L, Mid);
        Build(a, Right, Mid + 1, R);
        Merge(Node);
    }

   public:
    void Update(int i, int j, ll x) {
        if (i < 0)
            i = 0;
        if (j >= n)
            j = n - 1;
        if (n <= 0 || i > j)
            return;
        Update(i, j, x, 1, 0, n - 1);
    }

   private:
    void Update(int i, int j, ll x, int Node, int L, int R) {
        // debug() << imie(i) imie(j) imie(x) imie(Node) imie(L) imie(R);
        PushLazy(Node, R - L + 1);
        if (j < L || R < i)
            return;
        if (i <= L && R <= j)
            return Lazy[Node] = x, PushLazy(Node, R - L + 1);
        Update(i, j, x, Left, L, Mid);
        Update(i, j, x, Right, Mid + 1, R);
        Merge(Node);
    }

   public:
    Segment Query(int i, int j) {
        if (i < 0)
            i = 0;
        if (j >= n)
            j = n - 1;
        if (n <= 0 || i > j)
            return Segment();
        return Query(i, j, 1, 0, n - 1);
    }

   private:
    Segment Query(int i, int j, int Node, int L, int R) {
        PushLazy(Node, R - L + 1);
        if (j < L || R < i)
            return Segment();
        if (i <= L && R <= j)
            return Tree1[Node];
        return Unite(Query(i, j, Left, L, Mid), Query(i, j, Right, Mid + 1, R));
    }

   public:
    void Destroy(int i) {
        if (i < 0 || i >= n) {
            return;
        }
        return Destroy(i, 1, 0, n - 1);
    }

   private:
    void Destroy(int i, int Node, int L, int R) {
        PushLazy(Node, R - L + 1);
        if (i < L || R < i) {
            return;
        }
        // if (i == 3) {
        //     debug() << imie(Node) imie(L) imie(R);
        //     Tree1[Node].Debug();
        //     Tree2[Node].Debug();
        // }
        if (L == R) {
            return void(Tree1[Node].offset = Tree2[Node].offset = INF);
        }

        Destroy(i, Left, L, Mid);
        Destroy(i, Right, Mid + 1, R);
        Merge(Node);
        // if (i == 3) {
        //     debug() << imie(Node) imie(L) imie(R);
        //     Tree1[Node].Debug();
        //     Tree2[Node].Debug();
        // }
    }

   private:
    void Clear() {
        for (int Node = 0; Node <= 4 * n; Node++)
            Tree1[Node] = Segment(), Tree2[Node] = Segment(0), Lazy[Node] = EL;
        n = 0;
    }

   public:
    void Debug() {
        for (int Node = 1; Node <= 9; Node++) {
            debug() << imie(Node) imie(Lazy[Node]);
            Tree1[Node].Debug();
            Tree2[Node].Debug();
        }
        debug() << "-------------------------------------------";
    }

#undef Mid
#undef Left
#undef Right
};

SegmentTreeLazy myTree1;
SegmentTreeLazy myTree2;

int main() {
    int n, q;
    cin >> n >> q;

    vector<ll> a(n);
    for (ll& x : a) {
        scanf("%lld", &x);
    }

    vector<vector<int>> b(n), c(n);

    while (q--) {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        x--, y--, z--;
        b[x].push_back(y);
        c[x].push_back(z);
    }

    myTree1.Build(a);
    myTree1.Update(0, 0, -a[0]);

    vector<ll> neg_a = a;
    for (ll& x : neg_a) {
        x = -x;
    }

    myTree2.Build(neg_a);
    myTree2.Update(0, 0, -neg_a[0]);

    vector<ll> answer(n, -1);

    while (true) {
        // myTree1.Debug();

        // for (int i = 0; i < n; i++) {
        //     myTree1.Query(i, i).Debug();
        //     myTree2.Query(i, i).Debug();
        // }

        Segment s1 = myTree1.Query(0, n - 1);
        Segment s2 = myTree2.Query(0, n - 1);

        // debug() << imie(s1.value) imie(s1.offset) imie(s1.i);
        // debug() << imie(s2.value) imie(s2.offset) imie(s2.i);

        if (min(s1.value + s1.offset, s2.value + s2.offset) > INF2) {
            break;
        }

        int i = -1;

        if (s1 < s2) {
            i = s1.i;
            answer[i] = s1.value + s1.offset;
        } else {
            i = s2.i;
            answer[i] = s2.value + s2.offset;
        }

        // debug() << imie(i);
        // debug() << imie(b[i]);
        // debug() << imie(c[i]);
        // debug() << "";

        for (int j = 0; j < b[i].size(); j++) {
            myTree1.Update(max(i + 1, b[i][j]), c[i][j], answer[i] - a[i]);
            myTree2.Update(b[i][j], min(i - 1, c[i][j]), answer[i] + a[i]);
        }

        myTree1.Destroy(i);
        myTree2.Destroy(i);
    }

    answer[0] = 0;
    for (int i = 0; i < n; i++) {
        printf("%lld%c", answer[i], " \n"[i + 1 == n]);
    }
}

/*
5 1
1 2 3 4 5
1 1 5


3 4 5

*/
Copy
Fallout: New Vegas Baraa_Armoush
GNU G++17
225 ms
59.1 MB
Accepted