#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