Problem:
Wall Painting
Here stands a wall made of a number of vertical panels. The panels are not painted yet.
You have a number of robots each of which can paint panels in a single color, either red, green, or blue. Each of the robots, when activated, paints panels between a certain position and another certain position in a certain color. The panels painted and the color to paint them are fixed for each of the robots, but which of them are to be activated and the order of their activation can be arbitrarily decided.
You’d like to have the wall painted to have a high
aesthetic value
. Here, the aesthetic value of the wall is defined simply as the sum of aesthetic values of the panels of the wall, and the aesthetic value of a panel is defined to be:
0, if the panel is left unpainted.
The bonus value specified, if it is painted only in a single color, no matter how many times it is painted.
The penalty value specified, if it is once painted in a color and then overpainted in one or more different colors.
Input
The input consists of a single test case of the following format.
$n$ $m$ $x$ $y$
$c_1$ $l_1$ $r_1$
.
.
.
$c_m$ $l_m$ $r_m$
Here, $n$ is the number of the panels ($1 \leq n \leq 10^9$) and $m$ is the number of robots ($1 \leq m \leq 2 \times 10^5$). $x$ and $y$ are integers between $1$ and $10^5$, inclusive. $x$ is the bonus value and $-y$ is the penalty value. The panels of the wall are consecutively numbered $1$ through $n$. The $i$-th robot, when activated, paints all the panels of numbers $l_i$ through $r_i$ ($1 \leq l_i \leq r_i \leq n$) in color with color number $c_i$ ($c_i \in \{1, 2, 3\}$). Color numbers 1, 2, and 3 correspond to red, green, and blue, respectively.
Output
Output a single integer in a line which is the maximum achievable aesthetic value of the wall.
Sample Input 1
8 5 10 5
1 1 7
3 1 2
1 5 6
3 1 4
3 6 8
Sample Output 1
70
Sample Input 2
26 3 9 7
1 11 13
3 1 11
3 18 26
Sample Output 2
182
Sample Input 3
21 10 10 5
1 10 21
3 4 16
1 1 7
3 11 21
3 1 16
3 3 3
2 1 17
3 5 18
1 7 11
2 3 14
Sample Output 3
210
Sample Input 4
21 15 8 7
2 12 21
2 1 2
3 6 13
2 13 17
1 11 19
3 3 5
1 12 13
3 2 2
1 12 15
1 5 17
1 2 3
1 1 9
1 8 12
3 8 9
3 2 9
Sample Output 4
153

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#define sz(v) ((int)(v).size())
#define all(v) (v).begin(), (v).end()
using namespace std;
using lint = long long;
using pi = pair<int, int>;
const int MAXN = 600005;
const int MAXT = 2100000;

struct seg{
	lint tree[MAXT];
	int lim;
	void init(int n){
		for(lim = 1; lim <= n; lim <<= 1);
		fill(tree, tree + MAXT, -1e18);
	}
	void upd(int s, int e, lint x){
		auto upd = [&](int x, lint y){
			tree[x] = max(tree[x], y);
		};
		s += lim;
		e += lim;
		while(s < e){
			if(s%2 == 1) upd(s++, x);
			if(e%2 == 0) upd(e--, x);
			s >>= 1;
			e >>= 1;
		}
		if(s == e) upd(s, x);
	}
	lint query(int x){
		lint ret = -1e18;
		for(int i=x+lim; i; i>>=1) ret = max(ret, tree[i]);
		return ret;
	}
}seg[4][2];

struct interval{
	int s, e;
	int color;
	lint cost;
	bool operator<(const interval &i)const{
		return pi(s, e) < pi(i.s, i.e);
	}
};

vector<interval> a;
int n, m, x, y;
vector<int> v;
lint dp[MAXN];

int main(){
	scanf("%d %d %d %d",&n,&m,&x,&y);
	y += x;
	v.push_back(0);
	v.push_back(n);
	for(int i=0; i<m; i++){
		int c, l, r; scanf("%d %d %d",&c,&l,&r);
		v.push_back(l-1);
		v.push_back(r);
		a.push_back({l-1, r, c, 1ll * (r-l+1) * x});
	}
	sort(all(v));
	v.resize(unique(all(v)) - v.begin());
	for(int i=1; i<sz(v); i++){
		a.push_back({v[i-1], v[i], 0, 0});
	}
	for(auto &i : a){
		i.s = lower_bound(all(v), i.s) - v.begin();
		i.e = lower_bound(all(v), i.e) - v.begin();
	}
	sort(all(a));
	for(int i=0; i<8; i++) seg[i/2][i%2].init(sz(a));
	lint dap = 0;
	for(int i=sz(a)-1; i>=0; i--){
		dp[i] = max(dp[i], seg[a[i].color][0].query(a[i].e) - 1ll * v[a[i].e] * x);
		dp[i] = max(dp[i], seg[a[i].color][1].query(a[i].e) - 1ll * v[a[i].e] * (x + y));
		dp[i] += a[i].cost;
		dap = max(dap, dp[i]);
		for(int j=0; j<4; j++){
			if(a[i].color != j){
				seg[j][1].upd(a[i].s, a[i].e, dp[i] + 1ll * v[a[i].s] * (x + y));
			}
			else{
				seg[j][0].upd(a[i].s, a[i].e, dp[i] + 1ll * v[a[i].s] * x);
			}
		}
	}
	cout << dap << endl;
}
accuracy: 1
time_ms: 290
memory_kb: 156960
final_rank: 15

code_snippet: //dp
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
typedef   long long ll;
using namespace std;
const ll maxn = 100005;
struct robot{
    ll c,l,r;
}robots[maxn];
ll dp[maxn];
ll max(ll a,ll b,ll c){
    return max(max(a,b),max(b,c));
}
int main(int argc, char const *argv[])
{
    int n,m,x,y;
    memset(dp,0,sizeof(dp));
    scanf("%d%d%d%d",&n,&m,&x,&y);
    for (int i = 0; i < m; i++)
    {
        struct robot rb;
       scanf("%lld%lld%lld",&rb.c,&rb.l,&rb.r);
       robots[i]=rb; 
    }
    sort(robots,robots+m,[](robot&r1,robot&r2){
        return r1.r<r2.r||(r1.r==r2.r&&r1.l<r2.l);
    });
    dp[0]=(robots[0].r-robots[0].l+1)*x;
    for (int i = 1; i < m; i++)
    {
        ll res1=x*(robots[i].r-robots[i].l+1),res2=0,res3=0;
        for(int j=i-1;j>=0;j--){
            if(robots[j].r<robots[i].l)res1=max(res1,dp[j]+x*(robots[i].r-robots[i].l+1));//不重合
            else if(robots[j].l<robots[i].l){//如果完全重合的，跳过
                if(robots[j].c==robots[i].c){//颜色相同重合
                    res2=max(res2,dp[j]+x*(robots[i].r-robots[j].r));
                }else{//颜色不同重合
                    res3=max(res3,dp[j]-(x+y)*(robots[j].r-robots[i].l+1)+(robots[i].r-robots[j].r)*x);
                }
            }
        dp[i]=max(dp[i],max(res1,res2,res3));
        }
        
    }
    printf("%lld\n",*max_element(dp,dp+m));
    return 0;
}
accuracy: 0.13953488372093023
time_ms: 20
memory_kb: 4368
final_rank: 19

code_snippet: //dp
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#define LL long long
using namespace std;
const int maxn = 100005;
struct robot{
    int c,l,r;
}robots[maxn];
int dp[maxn];
int max(int a,int b,int c){
    return max(max(a,b),max(b,c));
}
int main(int argc, char const *argv[])
{
    int n,m,x,y;
    scanf("%d%d%d%d",&n,&m,&x,&y);
    for (int i = 0; i < m; i++)
    {
        struct robot rb;
       scanf("%d%d%d",&rb.c,&rb.l,&rb.r);
       robots[i]=rb; 
    }
    sort(robots,robots+m,[](robot&r1,robot&r2){
        return r1.r<r2.r||(r1.r==r2.r&&r1.l<r2.l);
    });
    dp[0]=(robots[0].r-robots[0].l+1)*x;
    for (int i = 1; i < m; i++)
    {
        int res1=x*(robots[i].r-robots[i].l+1),res2=0,res3=0;
        for(int j=i-1;j>=0;j--){
            if(robots[j].r<robots[i].l)res1=max(res1,dp[j]+x*(robots[i].r-robots[i].l+1));//不重合
            else if(robots[j].l<robots[i].l){
                if(robots[j].c==robots[i].c){//颜色相同重合
                    res2=max(res2,dp[j]+x*(robots[i].r-robots[j].r));
                }else{//颜色不同重合
                    res3=max(res3,dp[j]-(x+y)*(robots[j].r-robots[i].l+1)+(robots[i].r-robots[j].r)*x);
                }
            }
        }
        dp[i]=max(res1,res2,res3);
    }
    printf("%d\n",*max_element(dp,dp+m));
    return 0;
}
accuracy: 0.023255813953488372
time_ms: 20
memory_kb: 3548
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll =long long;
#define rep(i,a,b) for(ll i=(ll)(a);i<(ll)(b);i++)

template <class T,T (*op)(T,T),T (*e)()>
struct segtee{
    vector<T> seg;
    int size;
    segtee(int n_){
        size=1;
        while(size<n_) size*=2;
        seg.resize(size*2,e());
    }
    void set(int ind,T val){
        ind+=size;
        seg[ind]=val;
        while(ind>1){
            ind/=2;
            seg[ind]=op(seg[ind*2],seg[ind*2+1]);
        }
    }
    void addl(int ind,T val){
        set(ind,op(val,seg[ind+size]));
    }
    T get(int ind){
        return seg[ind+size];
    }
    T prod(int l,int r){
        l+=size,r+=size;
        T res=e();
        while(l<r){
            if(l&1) res=op(res,seg[l++]);
            if(r&1) res=op(res,seg[--r]);
            l/=2,r/=2;
        }
        return res;
    }
};

ll op(ll a,ll b){
    return max(a,b);
}
ll e(){
    return -(1ll<<55);
}

int main(){
    ll N,M,X,Y;
    cin>>N>>M>>X>>Y;
    set<ll> s;
    vector<ll> C(M),L(M),R(M),val(M);
    rep(i,0,M){
        cin>>C[i]>>L[i]>>R[i];
        C[i]--;
        R[i]++;
        s.insert(L[i]);
        s.insert(R[i]);
    }
    map<ll,int> m;
    for(int x:s){
        m[x]=m.size();
    }
    int len=m.size();
    vector<vector<int>> G(len),H(len);
    rep(i,0,M){
        G[m[L[i]]].push_back(i);
        H[m[R[i]]].push_back(i);
    }
    ll ans=0;
    segtee<ll,op,e> em(len);
    vector<segtee<ll,op,e>> seg(4,em);
    rep(i,0,len){
        for(auto x:H[i]){
            ans=max(ans,val[x]);
        }
        for(auto x:G[i]){
            ll tmp=ans;
            tmp=max(tmp,seg[C[x]].prod(m[L[x]],m[R[x]])+L[x]*X);
            tmp=max(tmp,seg[3]   .prod(m[L[x]],m[R[x]])+L[x]*(2*X+Y));
            tmp+=X*(R[x]-L[x]);
            val[x]=tmp;
            seg[C[x]].addl(m[R[x]],tmp-R[x]*X);
            seg[3]   .addl(m[R[x]],tmp-R[x]*(2*X+Y));
        }
    }
    cout<<ans<<"\n";
}
accuracy: 1
time_ms: 1000
memory_kb: 125428
final_rank: 16

code_snippet: #include <bits/stdc++.h>

#define rep(i,s,n) for(int i = int(s); i < int(n); i++)
#define rrep(i,s,n) for(int i = int(n) - 1; i >= int(s); i--)
#define all(v) (v).begin(), (v).end()

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template<class T>
bool chmin(T &a, T b) {
    if(a <= b) return false;
    a = b;
    return true;
}

template<class T>
bool chmax(T &a, T b) {
    if(a >= b) return false;
    a = b;
    return true;
}

using namespace std;

template <class S, S(*op)(S, S), S (*e) ()> struct segtree{
    private:
        int n;
        int sz;
        vector<S> data;
        void update(int i){
            data[i] = op(data[2*i], data[2*i+1]);
        }
    public:
        segtree(int n): segtree(vector<S>(n, e())) {}
        segtree(const vector<S> &v): n((int)v.size()), sz(1) {
            while(sz < n) sz *= 2;
            data = vector<S>(2*sz, e());
            rep(i,0,n){
                data[sz + i] = v[i];
            }
            rrep(i,1,sz) update(i);
        }

        void set(int p, S x){
            assert(0<= p && p < n);
            p += sz;
            data[p] = x;
            while(p > 1){
                p >>= 1;
                update(p);
            }
        }
        S get(int p){
            assert(0 <= p && p < n);
            return data[p + sz];
        }
        S prod(int l, int r){
            assert(0 <= l && l <= r && r <= n);
            S sml = e();
            S smr = e();
            l += sz;
            r += sz;
            while (l < r){
                if (l & 1) sml = op(sml, data[l++]);
                if (r & 1) smr = op(data[--r], smr);
                l >>= 1;
                r >>= 1;
            }
            return op(sml, smr);
        }

};

ll op(ll a, ll b){
    return max(a, b);
}
ll e(){
    return -1e18;
}

template <typename T>
vector<T> compress(vector<T> &X){
    vector<T> vals = X;
    sort(vals.begin(), vals.end());
    vals.erase(unique(vals.begin(), vals.end()), vals.end());
    return vals;
}

template <typename T>
int bisect(vector<T> &X, T v){
    return lower_bound(X.begin(), X.end(), v) - X.begin();
}

int main() {
    int n; cin >> n;
    int m; cin >> m;
    ll x, y; cin >> x >> y;

    vector<int> c(m);
    vector<ll> l(m), r(m);
    vector<ll> vs;
    rep(i,0,m){
        cin >> c[i] >> l[i] >> r[i];
        l[i]--;
        c[i]--;
        vs.push_back(l[i]);
        vs.push_back(r[i]);
    }
    vs.push_back(-1);

    
    vector<ll> v = compress(vs);
    int k = v.size();

    auto ind = [&](ll x) -> int {
        return bisect(v, x);
    };

    vector<vector<int>> bucket(k);
    rep(i,0,m){
        bucket[ind(l[i])].push_back(i);
    }

    vector<segtree<ll,op,e>> seg_same(3, segtree<ll,op,e>(vector<ll>(k, -1e18)));
    vector<segtree<ll,op,e>> seg_diff(3, segtree<ll,op,e>(vector<ll>(k, -1e18)));
    segtree<ll,op,e> seg_cop(vector<ll>(k, 0));

    rep(i,0,k){
        for (int j: bucket[i]){
            int indr = ind(r[j]);
            ll same_val = seg_same[c[j]].prod(i, indr) + x * r[j];
            ll same_dif1 = seg_diff[(c[j]+1)%3].prod(i, indr) + x * r[j] + (x + y) * l[j];
            ll same_dif2 = seg_diff[(c[j]+2)%3].prod(i, indr) + x * r[j] + (x + y) * l[j];
            ll same_cop = seg_cop.prod(0, i) + x * (r[j] - l[j]);
            ll nwv = max(max(same_val, same_dif1), max(same_dif2, same_cop));
            seg_cop.set(indr, max(seg_cop.get(indr), nwv));
            seg_same[c[j]].set(indr, max(seg_same[c[j]].get(indr), nwv - r[j] * x));
            seg_diff[c[j]].set(indr, max(seg_diff[c[j]].get(indr), nwv - r[j] * (2*x + y)));
        }
    }

    cout << seg_cop.prod(0, k) << '\n';


    
}
accuracy: 1
time_ms: 330
memory_kb: 90408
final_rank: 9

code_snippet: #include<bits/stdc++.h>

using namespace std;

#define ll long long
#define rep2(i, a, b) for(ll i = (a) ; i < (b);i++)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(iiiii, n)
#define ov3(a, b, c, name, ...) name
#define rep(...) ov3(__VA_ARGS__, rep2, rep1, rep0)(__VA_ARGS__)
#define vl vector<ll>
#define pll pair<ll, ll>
#define all(c) begin(c), end(c)
#define fore(e, v) for(auto &&e : v)
#define si(c) (ll)(c.size())
#define eb emplace_back
#define lb(v, c) lower_bound(all(v), (c)) - begin(v)


template<typename T, typename S>
bool chmin(T &x, const S &y) {
    return (x > y ? x = y, true : false);
}

template<typename T, typename S>
bool chmax(T &x, const S &y) {
    return (x < y ? x = y, true : false);
}

template<typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
    os << "{";
    rep(i, si(v)) {
        if (i) os << ", ";
        os << v[i];
    }
    return os << "}";
}

template<typename T, typename F>
struct segtree {
    int n, rn;
    vector<T> seg;
    F f;
    T id;

    segtree() = default;

    segtree(int rn, F f, T id) : rn(rn), f(f), id(id) {
        n = 1;
        while (n < rn) n <<= 1;
        seg.assign(n * 2, id);
    }

    void set(int i, T x) { seg[i + n] = x; }

    void build() {
        for (int k = n - 1; k > 0; k--) {
            seg[k] = f(seg[k * 2], seg[k * 2 + 1]);
        }
    }

    void update(int i, T x) {
        set(i, x);
        i += n;
        while (i >>= 1) seg[i] = f(seg[i * 2], seg[i * 2 + 1]);
    }

    T get(int i) { return seg[i + n]; }

    T prod(int l, int r) {
        T L = id, R = id;
        for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if (l & 1) L = f(L, seg[l++]);
            if (r & 1) R = f(seg[--r], R);
        }
        return f(L, R);
    }

};

int main() {
    int n, m;
    cin >> n >> m;
    ll x, y;
    cin >> x >> y;

    vl xs;
    vl l(m), r(m), c(m);
    rep(i, m) cin >> c[i] >> l[i] >> r[i], l[i]--, c[i]--;
    rep(i, m) xs.eb(l[i]), xs.eb(r[i]);
    sort(all(xs));
    xs.erase(unique(all(xs)), end(xs));


    vector<int> id(m);
    iota(all(id), 0);
    sort(all(id), [&](int i, int j) { return l[i] < l[j]; });

//    cerr << xs << endl;
    ll pre = 0, LL = 0;

    vector<vl > dp(3, vl(si(xs), -1e18));
    rep(i, 3) dp[i][0] = 0;
    auto maxf = [](ll x, ll y) { return max(x, y); };

    vector<segtree<ll, decltype(maxf)>> seg1(3, segtree<ll, decltype(maxf)>(si(xs), maxf, -1e18)),
            seg2(3, segtree<ll, decltype(maxf)>(si(xs), maxf, -1e18));
    rep(i, 3) seg1[i].update(0, 0), seg2[i].update(0, 0);


    fore(i, id) {
        int L = lb(xs, l[i]);
        int R = lb(xs, r[i]);
        while (LL <= L) {
            rep(t, 3)  chmax(pre, dp[t][LL]);
            LL++;
        }

        ll tmp = pre + (r[i] - l[i]) * x;

        rep(t, 3) {
            if (t != c[i]) {
//                rep(j, L + 1, R) {
//                    chmax(dp[c[i]][R], dp[t][j] - (xs[j] - l[i]) * (x * 2 + y) + (r[i] - l[i]) * x);
//                    chmax(tmp, dp[t][j] - xs[j] * (x * 2 + y) + (l[i] * (x * 2 + y) + (r[i] - l[i]) * x));
//                }
                chmax(tmp, seg1[t].prod(L + 1, R) + l[i] * (x * 2 + y) + (r[i] - l[i]) * x);
            } else {
//                rep(j, L + 1, R) {
//                    chmax(dp[c[i]][R], dp[t][j] + (r[i] - xs[j]) * x);
//                    chmax(tmp, dp[t][j] - xs[j] * x + r[i] * x);
//                }
                chmax(tmp, seg2[t].prod(L + 1, R) + r[i] * x);
            }
//            cout << t << " " << dp[c[i]][R] << endl;
            chmax(dp[c[i]][R], tmp);
            seg1[c[i]].update(R, max(seg1[c[i]].get(R), tmp - xs[R] * (x * 2 + y)));
            seg2[c[i]].update(R, max(seg2[c[i]].get(R), tmp - xs[R] * x));
        }
//        cout << i << " " << l[i] << " " << r[i] << " " << L << " " << R << " " << dp[c[i]][R] << endl;
//        rep(t, 3) cout << t << ": " << dp[t] << endl;
    }

//    cout << dp <<
//         endl;

    ll ma = 0;
    rep(i, 3)
        chmax(ma, *max_element(all(dp[i]))
        );
    cout << ma <<
         endl;
}
accuracy: 1
time_ms: 300
memory_kb: 79356
final_rank: 8

code_snippet: #include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

const long long INF = (3LL << 60);

class segment {
public:
	int col; long long l, r;
	segment() : col(-1), l(0), r(0) {}
	segment(int col_, long long l_, long long r_) : col(col_), l(l_), r(r_) {}
};

class segtree {
private:
	int sz;
	vector<long long> val;
public:
	segtree() : sz(0), val(vector<long long>()) {}
	segtree(int n) {
		sz = 1;
		while (sz < n) {
			sz *= 2;
		}
		val = vector<long long>(sz * 2, -INF);
	}
	void update(int pos, long long x) {
		pos += sz;
		val[pos] = x;
		while (pos > 1) {
			pos >>= 1;
			val[pos] = max(val[pos * 2], val[pos * 2 + 1]);
		}
	}
	long long rangemax(int l, int r) {
		l += sz;
		r += sz;
		long long res = -INF;
		while (l != r) {
			if (l & 1) res = max(res, val[l++]);
			if (r & 1) res = max(res, val[--r]);
			l >>= 1;
			r >>= 1;
		}
		return res;
	}
};
		

int main() {
	// step #1. input
	long long N; int M; long long X, Y;
	cin >> N >> M >> X >> Y;
	vector<segment> S(M);
	for (int i = 0; i < M; i++) {
		cin >> S[i].col >> S[i].l >> S[i].r;
		S[i].col -= 1;
		S[i].l -= 1;
	}
	
	// step #2. sort C, L, R
	sort(S.begin(), S.end(), [](const segment& s1, const segment& s2) {
		return s1.r != s2.r ? s1.r < s2.r : s1.l < s2.l;
	});
	vector<long long> rseq(M);
	for (int i = 0; i < M; i++) {
		rseq[i] = S[i].r;
	}
	
	// step #3. dynamic programming
	vector<int> perm(M);
	for (int i = 0; i < M; i++) {
		perm[i] = i;
	}
	sort(perm.begin(), perm.end(), [&](int va, int vb) {
		return S[va].l != S[vb].l ? S[va].l < S[vb].l : S[va].r < S[vb].r;
	});
	vector<long long> dp(M, -INF);
	vector<int> pre(M, -1);
	vector<segtree> seg(5);
	for (int i = 0; i < 5; i++) {
		seg[i] = segtree(M);
	}
	for (int i : perm) {
		int ptr = lower_bound(rseq.begin(), rseq.end(), S[i].l + 1) - rseq.begin();
		long long sub1 = max(seg[3].rangemax(0, ptr), 0LL);
		long long sub2 = seg[S[i].col].rangemax(ptr, i);
		long long sub3 = seg[4].rangemax(ptr, i);
		dp[i] = max(dp[i], sub1 + (S[i].r - S[i].l) * X);
		dp[i] = max(dp[i], sub2 + S[i].r * X);
		dp[i] = max(dp[i], sub3 + S[i].r * X + S[i].l * (X + Y));
		seg[S[i].col].update(i, dp[i] - S[i].r * X);
		seg[3].update(i, dp[i]);
		seg[4].update(i, dp[i] - S[i].r * (2 * X + Y));
	}
	
	// step #4. calculate & output answer
	long long answer = *max_element(dp.begin(), dp.end());
	cout << answer << endl;
	
	return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 33028
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
using namespace std;

class RangeMax {
	public:
	int size_ = 1;
	vector<long long> dat;
	
	void init(int sz) {
		while (size_ <= sz) size_ *= 2;
		dat.resize(size_ * 2 + 1, -(1LL << 60));
	}
	
	void update(int pos, long long x) {
		pos += size_;
		dat[pos] = max(dat[pos], x);
		while (pos >= 2) {
			pos >>= 1;
			dat[pos] = max(dat[pos * 2], dat[pos * 2 + 1]);
		}
	}
	
	long long query_(int l, int r, int a, int b, int u) {
		if (l <= a && b <= r) return dat[u];
		if (r <= a || b <= l) return -(1LL << 60);
		long long v1 = query_(l, r, a, ((a + b) >> 1), u * 2);
		long long v2 = query_(l, r, ((a + b) >> 1), b, u * 2 + 1);
		return max(v1, v2);
	}
	
	long long query(int l, int r) {
		return query_(l, r, 0, size_, 1);
	}
};

long long N, M, X, Y;
long long C[200009], L[200009], R[200009];
long long dp[200009];
vector<long long> Z;
RangeMax P1[3]; // Direct Value
RangeMax P2[3]; // Slope of X
RangeMax P3[3]; // Slope of X+Y

long long GetValue(int idx, int col) {
	if (C[idx] == col) {
		long long val1 = P2[col].query(L[idx] + 1, R[idx] + 1);
		long long val2 = P1[col].query(0, L[idx] + 1);
		val1 += 1LL * X * Z[R[idx]];
		val2 += 1LL * X * (Z[R[idx]] - Z[L[idx]]);
		// cout << "  # " << idx << " " << col << " " << val1 << " " << val2 << endl;
		return max(val1, val2);
	}
	else {
		long long val1 = P3[col].query(L[idx] + 1, R[idx] + 1);
		long long val2 = P1[col].query(0, L[idx] + 1);
		val1 += 1LL * (X + Y) * Z[R[idx]] - 1LL * Y * (Z[R[idx]] - Z[L[idx]]);
		val2 += 1LL * X * (Z[R[idx]] - Z[L[idx]]);
		// cout << "  $ " << idx << " " << col << " " << val1 << " " << val2 << endl;
		return max(val1, val2);
	}
}

int main() {
	// Input
	vector<tuple<int, int, int>> tup;
	cin >> N >> M >> X >> Y; Y = X + Y;
	for (int i = 1; i <= M; i++) {
		cin >> C[i] >> L[i] >> R[i]; L[i] -= 1; C[i] -= 1;
		tup.push_back(make_tuple(L[i], R[i], C[i]));
	}
	
	// Sorting & Compression
	sort(tup.begin(), tup.end());
	for (int i = 0; i < (int)tup.size(); i++) {
		C[i + 1] = get<2>(tup[i]);
		L[i + 1] = get<0>(tup[i]);
		R[i + 1] = get<1>(tup[i]);
		Z.push_back(L[i + 1]);
		Z.push_back(R[i + 1]);
	}
	Z.push_back(0);
	Z.push_back(N);
	sort(Z.begin(), Z.end());
	Z.erase(unique(Z.begin(), Z.end()), Z.end());
	for (int i = 1; i <= M; i++) L[i] = lower_bound(Z.begin(), Z.end(), L[i]) - Z.begin();
	for (int i = 1; i <= M; i++) R[i] = lower_bound(Z.begin(), Z.end(), R[i]) - Z.begin();
	
	// Initialize Segment Tree
	for (int i = 0; i < 3; i++) P1[i].init(Z.size() + 2);
	for (int i = 0; i < 3; i++) P2[i].init(Z.size() + 2);
	for (int i = 0; i < 3; i++) P3[i].init(Z.size() + 2);
	for (int i = 0; i < 3; i++) P1[i].update(0, 0);
	for (int i = 0; i < 3; i++) P2[i].update(0, 0);
	for (int i = 0; i < 3; i++) P3[i].update(0, 0);
	
	// Dynamic Programming
	for (int i = 1; i <= M; i++) dp[i] = -(1LL << 60);
	for (int i = 1; i <= M; i++) {
		for (int j = 0; j < 3; j++) {
			long long eval = GetValue(i, j);
			dp[i] = max(dp[i], eval);
		}
		P1[C[i]].update(R[i], dp[i]);
		P2[C[i]].update(R[i], dp[i] - Z[R[i]] * (X));
		P3[C[i]].update(R[i], dp[i] - Z[R[i]] * (X + Y));
		// cout << i << ": " << dp[i] << endl;
	}
	
	// Output
	long long Answer = 0;
	for (int i = 1; i <= M; i++) Answer = max(Answer, dp[i]);
	cout << Answer << endl;
	return 0;
}
accuracy: 1
time_ms: 390
memory_kb: 91536
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i,n) for(int i = 0; i < int(n); i++)
#define per(i,n) for(int i = (n) - 1; 0 <= i; i--)
#define rep2(i,l,r) for(int i = (l); i < int(r); i++)
#define per2(i,l,r) for(int i = (r) - 1; int(l) <= i; i--)
#define MM << " " <<
#define pb push_back
#define eb emplace_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define sz(x) (int)x.size()
#define each(e, x) for(auto &e : x)

template<class T>
void print(const vector<T> &v, T x = 0) {
    int n = sz(v);
    for(int i = 0; i < n; i++) {
        cout << v[i] + x << (i == n - 1 ? '\n' : ' ');
    }
    if(v.empty()) cout << '\n';
}

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

template<class T>
bool chmax(T &x, const T &y) {
    return (x < y) ? (x = y, true) : false;
}

template<class T>
bool chmin(T &x, const T &y) {
    return (x > y) ? (x = y, true) : false;
}

template<class T>
struct Seg {
        using F = function<T(T, T)>;
        vector<T> dat;
        int n;
        const F f;
        const T e;

        Seg(vector<T> v, F f, T e) : f(f), e(e) {
            int m = sz(v);
            n = 1;
            while(n < m) n *= 2;
            dat.assign(2 * n, e);
            rep(i,m) dat[n + i] = v[i];
            per2(i, 1, n) dat[i] = f(dat[2 * i], dat[2 * i + 1]);
        }

        void change(int i, T x) {
            i += n;
            dat[i] = f(dat[i], x);
            while(i > 1) {
                i /= 2;
                dat[i] = f(dat[2 * i], dat[i * 2 + 1]);
            }
        }

        T query(int l, int r, int k = 1, int L = 0, int R = -1) {
            if(R == -1) R = n;
            if(r <= L || R <= l) return e;
            if(l <= L && R <= r) return dat[k];
            int M = (L + R) / 2;
            return f(query(l, r, 2 * k, L, M),
                     query(l, r, 2 * k + 1, M , R));
        }
    };

struct P {
    int c, l, r;
};

int main() {
    int n, m; cin >> n >> m;
    ll x, y; cin >> x >> y;
    map<int, int> mp;
    vector<P> da(m);
    for(auto &i : da) {
        cin >> i.c >> i.l >> i.r;
        i.l--;
        i.c--;
        mp[i.l] = 0;
        mp[i.r] = 0;
    }
    {
        int c = 0;
        for(auto &i : mp) {
            i.second = c;
            c++;
        }
    }

    sort(all(da), [](const P &x, const P &y) {
        return x.l < y.l;
    });

    auto f = [](ll x, ll y) {return  max(x, y);};
    vector<Seg<ll>> dp1(3, Seg<ll>(vector<ll>(mp.size(), LLONG_MIN / 50), f, LLONG_MIN / 50));
    vector<Seg<ll>> dp2(3, Seg<ll>(vector<ll>(mp.size(), LLONG_MIN / 50), f, LLONG_MIN / 50));
    Seg<ll> dp3(vector<ll>(mp.size()), f, 0);

    for(auto &i : da) {
        ll now = dp3.query(0, mp[i.l] + 1) + (i.r - i.l) * x;
//        cerr << i.l MM i.r MM now  << endl;
        rep(j,3) {
            if(i.c == j) {
                chmax(now, dp2[j].query(mp[i.l], mp[i.r]) + i.r * x);
//            cerr << i.l MM i.r MM now MM j MM i.c MM dp2[j].query(mp[i.l], mp[i.r]) << endl;
            } else {
                chmax(now, dp1[j].query(mp[i.l], mp[i.r]) + i.r * x + i.l * (x + y));
//            cerr << i.l MM i.r MM now MM j MM i.c MM dp1[j].query(mp[i.l], mp[i.r]) << endl;
            }
        }
        dp1[i.c].change(mp[i.r], now - i.r * (2 * x + y));
        dp2[i.c].change(mp[i.r], now - i.r * x);
        dp3.change(mp[i.r], now);
    }

    ll ans = dp3.query(0, sz(mp));
    rep(i,3) {
        chmax(ans, dp1[i].query(0, sz(mp)));
        chmax(ans, dp2[i].query(0, sz(mp)));
    }

    cout << ans << endl;
}
accuracy: 1
time_ms: 740
memory_kb: 84740
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i, n) for(int i = 0; i < n ; i++)
#define per(i, n) for(int i = (n)-1; 0 <= i; i--)
#define rep2(i, l, r) for(int i = (l); i < r; i++)
#define per2(i, l, r) for(int i = (r)-1; i >= l; i--)
#define MM << " " <<
#define pb push_back
#define eb emplace_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define sz(x) (int)x.size()

template<typename T>
void print(const vector<T> &v, T x = 0){
    int n = sz(v);
    rep(i, n) cout << v[i]+x << (i == n-1? '\n'  : ' ');
    if(v.empty()) cout << '\n';
}

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

template<typename T>
bool chmax(T &x, const T &y){
    return (x < y)? (x = y, true) : false;
}

template<typename T>
bool chmin(T &x, const T &y){
    return (x > y)? (x = y, true) : false;
}

const ll MOD = 1000000007;

template<class T>
using minheap = priority_queue<T, vector<T>, greater<T>>;

template<class T>
using maxheap = priority_queue<T>;

template<typename T>
int lb(const vector<T> &v, T x){
    return lower_bound(all(v), x) - begin(v);
}

template<typename T>
int ub(const vector<T> &v, T x){
    return upper_bound(all(v), x)-begin(v);
}

template<typename T>
void rearrange(vector<T> &v){
    sort(all(v));
    v.erase(unique(all(v)), end(v));
}

struct io_setup{
    io_setup(){
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cout << fixed << setprecision(15);
    }
} io_setup;

template<typename Monoid>
struct Segment_Tree {
    using F = function<Monoid(Monoid, Monoid)>;
    int n;
    vector<Monoid> seg;
    const F f;
    const Monoid e1;
    Segment_Tree(const vector<Monoid> &v, const F &f, const Monoid &e1) : f(f), e1(e1) {
        int m = sz(v);
        n = 1;
        while (n < m) n <<= 1;
        seg.assign(2 * n, e1);
        copy(all(v), seg.begin() + n);
        per(i, n) seg[i] = f(seg[2 * i], seg[2 * i + 1]);
    }
    Segment_Tree(int m, const Monoid &x, const F &f, const Monoid &e1) : Segment_Tree(vector<Monoid>(m, x), f, e1) {}
    void change(int i, const Monoid &x, bool update = true) {
        if (update)
            seg[i + n] = x;
        else
            seg[i + n] = f(seg[i + n], x);
        i += n;
        while (i >>= 1) seg[i] = f(seg[2 * i], seg[2 * i + 1]);
    }
    Monoid query(int l, int r) const {
        l = max(l, 0), r = min(r, n);
        Monoid L = e1, R = e1;
        l += n, r += n;
        while (l < r) {
            if (l & 1) L = f(L, seg[l++]);
            if (r & 1) R = f(seg[--r], R);
            l >>= 1, r >>= 1;
        }
        return f(L, R);
    }
};

int main() {
    ll n, m, x, y;
    cin >> n >> m >> x >> y;
    ll inf = 1e18;
    vector<ll> c(m), l(m), r(m);
    rep(i, m) cin >> c[i] >> l[i] >> r[i], c[i]--, l[i]--;
    vector<ll> xs{-1};
    rep(i, m) xs.eb(l[i]), xs.eb(r[i]);
    rearrange(xs);
    n = sz(xs);
    vector<pair<pll, ll>> v;
    rep(i, m) v.eb(pair(l[i], r[i]), c[i]);
    sort(all(v));
    auto F = [](ll a, ll b){return max(a, b);};
    Segment_Tree<ll> seg(n, -inf, F, -inf);
    vector<Segment_Tree<ll>> segs(3, Segment_Tree<ll>(n, -inf, F, -inf)), segd(3, Segment_Tree<ll>(n, -inf, F, -inf));
    seg.change(0, 0);
    for (auto [lr, nc] : v) {
        auto [nl, nr] = lr;
        int il = lb(xs, nl), ir = lb(xs, nr);
        ll val = -inf, nlen = nr - nl;
        chmax(val, seg.query(0, il + 1) + x * nlen);
//        if (nl == 5) {
//            print(segd[0].seg);
//        }
        rep(i, 3) {
//            cout << val << ' ';
            if (i == nc)
                chmax(val, segs[i].query(il + 1, ir) + x * nlen + x * nl);
            else
                chmax(val, segd[i].query(il + 1, ir) + x * nlen + (x * 2 + y) * nl);
//            cout << val << endl;
        }
//        cout << nl << ' ' << nr << ' ' << nc << ' ' << val << endl;
        seg.change(ir, val, false);
        segs[nc].change(ir, val - x * nr, false), segd[nc].change(ir, val - (x * 2 + y) * nr, false);
    }
    cout << seg.query(0, n) << endl;
}
accuracy: 1
time_ms: 250
memory_kb: 86340
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, n) for(int i = 0; i < n; i++)

template <class T>
bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}
constexpr ll INF = 1e18;
constexpr ll e = -INF;

using vll = vector<long long>;

struct stmax {
	int n;
	vector<ll> dat;
	stmax(int n) : n(n), dat(n + n, e) {}
	int left(int par) { return par * 2; }
	int right(int par) { return left(par) + 1; }
	void update(int idx, ll value) {
		idx += n;
		dat[idx] = value;
		idx >>= 1;
		while(idx) {
			dat[idx] = max(dat[left(idx)], dat[right(idx)]);
			idx >>= 1;
		}
	}

	void kaizen(int idx, ll value) {
		ll old = get(idx, idx + 1);
		if(value > old) update(idx, value);
	}

	ll get(int l, int r = -1) {
		if(r < 0) r = l + 1;
		assert(0 <= l && l <= r && r <= n);
		l += n;
		r += n;
		ll ret = e;
		while(l < r) {
			if(l & 1) {
				chmax(ret, dat[l]);
				l++;
			}
			l >>= 1;
			if(r & 1) {
				chmax(ret, dat[r - 1]);
				r--;
			}
			r >>= 1;
		}
		return ret;
	}
};

ll solve(ll n) {
	int m;
	ll x, y;
	cin >> m >> x >> y;
	vll ps;
	vector<tuple<int, ll, ll>> cxy;
	rep(i, m) {
		int c;
		cin >> c;
		c--;
		ll l, r;
		cin >> l >> r;
		l--;
		ps.push_back(l);
		ps.push_back(r);
		cxy.emplace_back(c, l, r);
	}
	sort(begin(ps), end(ps));
	auto idx = [&](ll value) -> int {
		auto it = lower_bound(ps.begin(), ps.end(), value);
		if(it == ps.end() || *it != value) return -1;
		return int(it - ps.begin());
	};

	int len = int(ps.size());
	vector<stmax> same(3, len);
	vector<stmax> diff(3, len);

	ll penalty_large = x + x + y;
	ll penalty_small = x;

	auto update_same = [&](int color, int pos, ll value) { same[color].kaizen(pos, value - penalty_small * ps[pos]); };
	auto update_diff = [&](int color, int pos, ll value) { diff[color].kaizen(pos, value - penalty_large * ps[pos]); };

	rep(i, 3) {
		update_same(i, 0, 0LL);
		update_diff(i, 0, 0LL);
	}


	sort(begin(cxy), end(cxy), [](tuple<int, ll, ll> lef, tuple<int, ll, ll> rig) -> bool { return get<1>(lef) < get<1>(rig); });

	ll ans = 0LL;
	auto it = cxy.begin();
	rep(leftside, len) {
		const ll leftpos = ps[leftside];
		rep(color, 3) {
			chmax(ans, same[color].get(leftside) + penalty_small * leftpos);
			chmax(ans, diff[color].get(leftside) + penalty_large * leftpos);
		}
		while(it != cxy.end() && get<1>(*it) == leftpos) {
			int c;
			ll r;
			tie(c, ignore, r) = *it;
			it++;
			int right = idx(r);
			ll value = ans;
			rep(precolor, 3) {
				if(c == precolor) {
					chmax(value, same[precolor].get(leftside, right + 1) + penalty_small * leftpos);
				} else {
					chmax(value, diff[precolor].get(leftside, right + 1) + penalty_large * leftpos);
				}
			}
			value += (r - leftpos) * x;

			update_same(c, right, value);
			update_diff(c, right, value);
		}
	}

	return ans;
}

int main() {
	ll n;
	while(cin >> n && n) cout << solve(n) << '\n';
}
accuracy: 1
time_ms: 250
memory_kb: 56264
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, n) for(int i = 0; i < n; i++)

template <class T>
bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}
constexpr ll INF = 1e18;
constexpr ll e = -INF;

using vll = vector<long long>;

template <class T>
void view(const T &e) {
	cerr << e;
}
void view(const ll &e) {
	if(-e > INF / 2)
		cerr << "-INF";
	else if(e > INF / 2)
		cerr << "INF";
	else
		cerr << e;
}
template <class T>
void view(const vector<T> &v) {
	if(v.empty()) {
		cerr << "{ }";
		return;
	}
	cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		cerr << ", ";
	}
	cerr << "\b\b }";
}

void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	view(H);
	cerr << ", ";
	debug_out(T...);
}

#ifdef LOC
#define debug(...)                                           \
	do {                                                     \
		cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                              \
		cerr << "\b\b]\n";                                   \
	} while(0)
#else
#define debug(...) void(0)
#endif

struct stmax {
	int n;
	vector<ll> dat;
	stmax(int n) : n(n), dat(n + n, e) {}
	int left(int par) { return par * 2; }
	int right(int par) { return left(par) + 1; }
	void update(int idx, ll value) {
		idx += n;
		dat[idx] = value;
		idx >>= 1;
		while(idx) {
			dat[idx] = max(dat[left(idx)], dat[right(idx)]);
			idx >>= 1;
		}
	}

	void kaizen(int idx, ll value) {
		ll old = get(idx, idx + 1);
		if(value > old) update(idx, value);
	}

	ll get(int l, int r = -1) {
		if(r < 0) r = l + 1;
		assert(0 <= l && l <= r && r <= n);
		l += n;
		r += n;
		ll ret = e;
		while(l < r) {
			if(l & 1) {
				chmax(ret, dat[l]);
				l++;
			}
			l >>= 1;
			if(r & 1) {
				chmax(ret, dat[r - 1]);
				r--;
			}
			r >>= 1;
		}
		return ret;
	}

	void print() {
#ifdef LOC
		cerr << '[' << ' ';
		rep(i, n) {
			view(get(i));
			cerr << ' ';
		}
		cerr << "]";
		cerr << '\n';
#endif
	}
};

ll solve(ll n) {
	int m;
	ll x, y;
	cin >> m >> x >> y;
	vll ps;
	vector<tuple<int, ll, ll>> cxy;
	rep(i, m) {
		int c;
		cin >> c;
		c--;
		ll l, r;
		cin >> l >> r;
		l--;
		ps.push_back(l);
		ps.push_back(r);
		cxy.emplace_back(c, l, r);
	}
	sort(begin(ps), end(ps));
	auto idx = [&](ll value) -> int {
		auto it = lower_bound(ps.begin(), ps.end(), value);
		if(it == ps.end() || *it != value) return -1;
		return int(it - ps.begin());
	};

	int len = int(ps.size());
	vector<stmax> same(3, len);
	vector<stmax> diff(3, len);

	ll penalty_large = x + x + y;
	ll penalty_small = x;

	auto update_same = [&](int color, int pos, ll value) { same[color].kaizen(pos, value - penalty_small * ps[pos]); };
	auto update_diff = [&](int color, int pos, ll value) { diff[color].kaizen(pos, value - penalty_large * ps[pos]); };

	rep(i, 3) {
		update_same(i, 0, 0LL);
		update_diff(i, 0, 0LL);
	}

	same.front().print();

	sort(begin(cxy), end(cxy), [](tuple<int, ll, ll> lef, tuple<int, ll, ll> rig) -> bool { return get<1>(lef) < get<1>(rig); });

	ll ans = 0LL;
	debug(ps);
	auto it = cxy.begin();
	rep(leftside, len) {
		const ll leftpos = ps[leftside];
		rep(color, 3) {
			chmax(ans, same[color].get(leftside) + penalty_small * leftpos);
			chmax(ans, diff[color].get(leftside) + penalty_large * leftpos);
		}
		while(it != cxy.end() && get<1>(*it) == leftpos) {
			int c;
			ll r;
			tie(c, ignore, r) = *it;
			it++;
			int right = idx(r);
			ll value = ans;
			rep(precolor, 3) {
				if(c == precolor) {
					chmax(value, same[precolor].get(leftside, right + 1) + penalty_small * leftpos);
				} else {
					chmax(value, diff[precolor].get(leftside, right + 1) + penalty_large * leftpos);
				}
			}
			value += (r - leftpos) * x;

			update_same(c, right, value);
			update_diff(c, right, value);
		}
	}

	return ans;
}

int main() {
	ll n;
	while(cin >> n && n) cout << solve(n) << '\n';
}
accuracy: 1
time_ms: 250
memory_kb: 56824
final_rank: 3

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}

int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
template<typename T>
struct SegT {
private:
	int sz; vector<T> node;
	T init_c;
	function<T(T, T)> f;
public:
	SegT(vector<T> v, T _init_c, function<T(T, T)> _f) {
		init_c = _init_c; f = _f;
		int n = v.size();
		sz = 1;
		while (sz < n)sz *= 2;
		node.resize(2 * sz - 1, init_c);
		rep(i, n) {
			node[i + sz - 1] = v[i];
		}
		per(i, sz - 1) {
			node[i] = f(node[2 * i + 1], node[2 * i + 2]);
		}
	}
	SegT() { ; }
	void init(int n, T _init_c, function<T(T, T)> _f) {
		init_c = _init_c; f = _f;
		sz = 1;
		while (sz < n)sz *= 2;
		node.resize(2 * sz - 1, init_c);
	}
	void update(int k, T a) {
		k += sz - 1;
		node[k] = f(node[k],a);
		while (k > 0) {
			k = (k - 1) / 2;
			node[k] = f(node[k * 2 + 1], node[k * 2 + 2]);
		}
	}
	T query(int a, int b, int k = 0, int l = 0, int r = -1) {
		if (r < 0)r = sz;
		if (r <= a || b <= l)return init_c;
		else if (a <= l && r <= b)return node[k];
		else {
			T vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			T vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return f(vl, vr);
		}
	}
	//k以上でf(x,node[y+sz-1])をtrueにするような最小のy
	int searchloc(int le, T x, function<bool(T, T)> comp) {
		int  k = le + sz - 1;
		if (comp(x, node[k]))return le;
		x = f(x, node[k]);
		while (k > 0) {
			int mem = k;
			k = (k - 1) / 2;
			if (2 * k + 1 == mem) {
				if (comp(x, node[2 * k + 2])) {
					k = 2 * k + 2; break;
				}
				x = f(x, node[2 * k + 2]);
			}
		}
		if (k == 0)return sz;
		while (k < sz - 1) {
			if (comp(x, node[2 * k + 1])) {
				k = 2 * k + 1;
			}
			else {
				x = f(x, node[2 * k + 1]);
				k = 2 * k + 2;
			}
		}
		return k - (sz - 1);
	}
};


void solve(){
	int steru; cin >> steru;//steru sayonara~~
	int n; cin >> n;
	ll x, y; cin >> x >> y;
	vector<int> c(n), l(n), r(n);
	rep(i, n) {
		cin >> c[i] >> l[i] >> r[i]; r[i]++; c[i]--;
	}
	vector<int> v;
	rep(i, n) {
		v.push_back(l[i]);
		v.push_back(r[i]);
	}
	sort(all(v));
	v.erase(unique(all(v)), v.end());
	
	rep(i, n) {
		l[i] = lower_bound(all(v), l[i]) - v.begin();
		r[i] = lower_bound(all(v), r[i]) - v.begin();
	}
	auto f = [&](ll a, ll b) {return max(a, b); };
	SegT<ll> ast[3],bst[3];
	rep(i, 3) {
		ast[i].init(v.size(), -INF, f);
		bst[i].init(v.size(), -INF, f);
	}
	vector<vector<P>> G(v.size());
	rep(i, n) {
		G[l[i]].push_back({ r[i],c[i] });
	}
	vector<ll> dp(v.size(),-INF);
	dp[0] = 0;
	rep(i, dp.size()) {
		if (i > 0)chmax(dp[i], dp[i - 1]);
		rep(col, 3) {
			ll val = ast[col].query(i, i + 1);
			val += x * v[i];
			chmax(dp[i], val);
			val = bst[col].query(i, i + 1);
			val += x * v[i] + (x + y) * v[i];
			chmax(dp[i], val);
		}
		rep(col, 3) {
			ast[col].update(i, dp[i] - x * v[i]);
			bst[col].update(i, dp[i] - (2 * x + y) * v[i]);
		}
		for (P p : G[i]) {
			int r = p.first;
			int c = p.second;
			ll ma = -INF;
			rep(col, 3) {
				ll val;
				if (col == c) {
					val = ast[col].query(i, r) + x * v[r];
				}
				else {
					val = bst[col].query(i, r) + x * v[r] + (x + y) * v[i];
				}
				chmax(ma, val);
			}
			ast[c].update(r, ma - x * v[r]);
			bst[c].update(r, ma - x * v[r] - (x + y) * v[r]);
		}
	}
	cout << dp.back() << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//init();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 700
memory_kb: 83176
final_rank: 13

code_snippet: #include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
#include<cassert>
#include<set>
#include<complex>
#include<numeric>
#include<functional>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long int LL;
typedef pair<int,int> P;
typedef pair<LL,LL> LP;
const LL INF=1LL<<60;
const LL MAX=1e9+7;

void array_show(int *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
template<typename T> ostream& operator<<(ostream& os,const vector<T>& v1){
    int n=v1.size();
    for(int i=0;i<n;i++){
        if(i)os<<" ";
        os<<v1[i];
    }
    return os;
}
template<typename T1,typename T2> ostream& operator<<(ostream& os,const pair<T1,T2>& p){
    os<<p.first<<" "<<p.second;
    return os;
}
template<typename T> istream& operator>>(istream& is,vector<T>& v1){
    int n=v1.size();
    for(int i=0;i<n;i++)is>>v1[i];
    return is;
}
template<typename T1,typename T2> istream& operator>>(istream& is,pair<T1,T2>& p){
    is>>p.first>>p.second;
    return is;
}

template <typename T> class seg_tree{
    //monoid
private:
    function<T(T,T)> func;
    T e;
    int N,n=-1;
    vector<T> seg;

    void init(){
        assert(n>=0);
        int i;
        for(i=0;(1<<i)<n;i++);
        N=(1<<i)-1;
        seg.assign(2*(N+1),e);
    }

    void init_reload(){
        for(int i=N-1;i>=0;i--){
            seg[i]=func(seg[2*i+1],seg[2*i+2]);
        }
    }
    
    void update(int pos){
        T a=func(seg[pos*2+1],seg[pos*2+2]);
        if(seg[pos]==a)return;
        seg[pos]=a;
        if(pos==0)return;
        update((pos-1)/2);
    }

public:
    seg_tree(function<T(T,T)> _func,T _e,int _n):func(_func),e(_e),n(_n){
        init();
    }
    seg_tree(function<T(T,T)> _func,T _e,vector<T> vec):func(_func),e(_e){
        n=vec.size();
        init();
        for(int i=0;i<n;i++){
            seg[N+i]=vec[i];
        }
        init_reload();
    }
    seg_tree(function<T(T,T)> _func,T _e,int _n,T a):func(_func),e(_e),n(_n){
        init(e);
        for(int i=0;i<n;i++){
            seg[N+i]=a;
        }
        init_reload();
    }

    int size()const{
        return n;
    }

    void set(int pos,T a){
        assert(pos>=0 && pos<=N);
        pos+=N;
        seg[pos]=a;
        update((pos-1)/2);
    }

    T get(const int pos)const{
        return seg[N+pos];
    }

    T search(int a,int b,int l,int r,int x){//[a,b) search
        if(a<=l && r<=b)return seg[x];
        int m=(l+r)/2;
        if(b<=m)return search(a,b,l,m,2*x+1);
        if(m<=a)return search(a,b,m,r,2*x+2);
        return func(search(a,m,l,m,2*x+1),search(m,b,m,r,2*x+2));
    }
    T search(int a,int b){
        assert(a<b);
        return search(a,b,0,N+1,0);
    }
    T search(){
        return search(0,size());
    }

    int max_right(function<bool(T)>& g,int pos,int l,int r,int x,T& y){
        //suppose that S is return value, g(func(pos,..,S-1))=true,g(func(pos,..,S))=false
        if(pos<=l && g(func(y,seg[x]))){
            y=func(y,seg[x]);
            return r;
        }
        if(l+1==r)return l;
        int m=(l+r)/2;
        if(pos<m){
            int s=max_right(g,pos,l,m,2*x+1,y);
            if(s<m)return s;
        }
        return max_right(g,pos,m,r,2*x+2,y);
    }
    int max_right(function<bool(T)> g,int pos){
        T y=e;
        int s=max_right(g,pos,0,N+1,0,y);
        return min(s,n);
    }

    int min_left(function<bool(T)>& g,int pos,int l,int r,int x,T& y){
        //suppose that S is return value, g(func(S,..,pos-1))=true,g(func(S-1,..,pos-1))=false
        int s;
        if(r<=pos && g(func(seg[x],y))){
            y=func(seg[x],y);
            return l;
        }
        if(l+1==r)return r;
        int m=(l+r)/2;
        if(m<pos){
            s=min_left(g,pos,m,r,2*x+2,y);
            if(m<s)return s;
        }
        return min_left(g,pos,l,m,2*x+1,y);
    }
    int min_left(function<bool(T)> g,int pos){
        assert(pos>=0);
        if(pos==0)return 0;
        T y=e;
        return min_left(g,pos,0,N+1,0,y);
    }
};

template<typename T> class Compress{
    //Compress<int> ca({5,1,2,3});
    //ca.id(5) //=3
private:
    vector<int> id_perm;//v1 index -> vec index
public:
    vector<T> vec;
    void init(const vector<T>& v1){
        int n=v1.size();
        int i,j;
        id_perm.assign(n,-1);
        vector<pair<T,int>> va;
        for(i=0;i<n;i++){
            va.push_back({v1[i],i});
        }
        sort(va.begin(),va.end());
        vec.clear();
        for(i=0,j=-1;i<n;i++){
            if(vec.empty() || vec.back()!=va[i].first){
                vec.push_back(va[i].first);
                j++;
            }
            id_perm[va[i].second]=j;
        }
    }

    Compress(const vector<T> v1){
        init(v1);
    }

    vector<int> get_id_perm()const{
        return id_perm;
    }

    int id(const T a){
        auto itr=lower_bound(vec.begin(),vec.end(),a);
        assert(itr!=vec.end());//return -1?
        assert(*itr==a);
        return itr-vec.begin();
    }
};

namespace sol{
    typedef tuple<LL,LL,LL> T;
    LL op(LL a,LL b){return max(a,b);}

    void solve(){
        LL n,m;
        int i,j,k;
        LL a,b,c;
        LL p,q,r;
        LL x,y;
        cin>>n>>m>>x>>y;
        seg_tree<LL> seg(op,-INF,2*m+2),seg2(op,-INF,2*m+2);
        vector<seg_tree<LL>> vse(3,seg_tree<LL>(op,-INF,2*m+2));
        vector<LL> va;
        vector<T> vt;
        for(i=0;i<m;i++){
            cin>>c>>a>>b;
            a--,c--;
            va.push_back(a),va.push_back(b);
            vt.push_back({a,b,c});
        }
        Compress<LL> com(va);
        for(i=0;i<m;i++){
            tie(a,b,c)=vt[i];
            a=com.id(a),b=com.id(b);
            vt[i]=T(a,b,c);
        }
        sort(vt.begin(),vt.end());
        for(i=0;i<m;i++){
            tie(a,b,c)=vt[i];
            q=com.vec[a],r=com.vec[b];
            p=(r-q)*x;
            p=max(p,seg2.search(0,a+1)+(r-q)*x);
            p=max(p,seg.search(a,b)+q*(x+y)+r*x);
            p=max(p,vse[c].search(a,b)+r*x);
            if(seg2.get(b)<p){
                seg.set(b,p-r*(2*x+y));
                seg2.set(b,p);
            }
            vse[c].set(b,max(vse[c].get(b),p-r*x));
        }
        cout<<seg2.search()<<endl;
    }
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    sol::solve();
}
accuracy: 1
time_ms: 250
memory_kb: 75256
final_rank: 5

code_snippet: #include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
#include<cassert>
#include<set>
#include<complex>
#include<numeric>
#include<functional>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long int LL;
typedef pair<int,int> P;
typedef pair<LL,LL> LP;
const LL INF=1LL<<60;
const LL MAX=1e9+7;

void array_show(int *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
template<typename T> ostream& operator<<(ostream& os,const vector<T>& v1){
    int n=v1.size();
    for(int i=0;i<n;i++){
        if(i)os<<" ";
        os<<v1[i];
    }
    return os;
}
template<typename T1,typename T2> ostream& operator<<(ostream& os,const pair<T1,T2>& p){
    os<<p.first<<" "<<p.second;
    return os;
}
template<typename T> istream& operator>>(istream& is,vector<T>& v1){
    int n=v1.size();
    for(int i=0;i<n;i++)is>>v1[i];
    return is;
}
template<typename T1,typename T2> istream& operator>>(istream& is,pair<T1,T2>& p){
    is>>p.first>>p.second;
    return is;
}

template <typename T> class seg_tree{
    //monoid
private:
    function<T(T,T)> func;
    T e;
    int N,n=-1;
    vector<T> seg;

    void init(){
        assert(n>=0);
        int i;
        for(i=0;(1<<i)<n;i++);
        N=(1<<i)-1;
        seg.assign(2*(N+1),e);
    }

    void init_reload(){
        for(int i=N-1;i>=0;i--){
            seg[i]=func(seg[2*i+1],seg[2*i+2]);
        }
    }
    
    void update(int pos){
        T a=func(seg[pos*2+1],seg[pos*2+2]);
        if(seg[pos]==a)return;
        seg[pos]=a;
        if(pos==0)return;
        update((pos-1)/2);
    }

public:
    seg_tree(function<T(T,T)> _func,T _e,int _n):func(_func),e(_e),n(_n){
        init();
    }
    seg_tree(function<T(T,T)> _func,T _e,vector<T> vec):func(_func),e(_e){
        n=vec.size();
        init();
        for(int i=0;i<n;i++){
            seg[N+i]=vec[i];
        }
        init_reload();
    }
    seg_tree(function<T(T,T)> _func,T _e,int _n,T a):func(_func),e(_e),n(_n){
        init(e);
        for(int i=0;i<n;i++){
            seg[N+i]=a;
        }
        init_reload();
    }

    int size()const{
        return n;
    }

    void set(int pos,T a){
        assert(pos>=0 && pos<=N);
        pos+=N;
        seg[pos]=a;
        update((pos-1)/2);
    }

    T search(int a,int b,int l,int r,int x){//[a,b) search
        if(a<=l && r<=b)return seg[x];
        int m=(l+r)/2;
        if(b<=m)return search(a,b,l,m,2*x+1);
        if(m<=a)return search(a,b,m,r,2*x+2);
        return func(search(a,m,l,m,2*x+1),search(m,b,m,r,2*x+2));
    }
    T search(int a,int b){
        assert(a<b);
        return search(a,b,0,N+1,0);
    }
    T search(){
        return search(0,size());
    }

    int max_right(function<bool(T)>& g,int pos,int l,int r,int x,T& y){
        //suppose that S is return value, g(func(pos,..,S-1))=true,g(func(pos,..,S))=false
        if(pos<=l && g(func(y,seg[x]))){
            y=func(y,seg[x]);
            return r;
        }
        if(l+1==r)return l;
        int m=(l+r)/2;
        if(pos<m){
            int s=max_right(g,pos,l,m,2*x+1,y);
            if(s<m)return s;
        }
        return max_right(g,pos,m,r,2*x+2,y);
    }
    int max_right(function<bool(T)> g,int pos){
        T y=e;
        int s=max_right(g,pos,0,N+1,0,y);
        return min(s,n);
    }

    int min_left(function<bool(T)>& g,int pos,int l,int r,int x,T& y){
        //suppose that S is return value, g(func(S,..,pos-1))=true,g(func(S-1,..,pos-1))=false
        int s;
        if(r<=pos && g(func(seg[x],y))){
            y=func(seg[x],y);
            return l;
        }
        if(l+1==r)return r;
        int m=(l+r)/2;
        if(m<pos){
            s=min_left(g,pos,m,r,2*x+2,y);
            if(m<s)return s;
        }
        return min_left(g,pos,l,m,2*x+1,y);
    }
    int min_left(function<bool(T)> g,int pos){
        assert(pos>=0);
        if(pos==0)return 0;
        T y=e;
        return min_left(g,pos,0,N+1,0,y);
    }
};

template<typename T> class Compress{
    //Compress<int> ca({5,1,2,3});
    //ca.id(5) //=3
private:
    vector<int> id_perm;//v1 index -> vec index
public:
    vector<T> vec;
    void init(const vector<T>& v1){
        int n=v1.size();
        int i,j;
        id_perm.assign(n,-1);
        vector<pair<T,int>> va;
        for(i=0;i<n;i++){
            va.push_back({v1[i],i});
        }
        sort(va.begin(),va.end());
        vec.clear();
        for(i=0,j=-1;i<n;i++){
            if(vec.empty() || vec.back()!=va[i].first){
                vec.push_back(va[i].first);
                j++;
            }
            id_perm[va[i].second]=j;
        }
    }

    Compress(const vector<T> v1){
        init(v1);
    }

    vector<int> get_id_perm()const{
        return id_perm;
    }

    int id(const T a){
        auto itr=lower_bound(vec.begin(),vec.end(),a);
        assert(itr!=vec.end());//return -1?
        assert(*itr==a);
        return itr-vec.begin();
    }
};

namespace sol{
    typedef tuple<LL,LL,LL> T;
    LL op(LL a,LL b){return max(a,b);}

    void solve(){
        LL n,m;
        int i,j,k;
        LL a,b,c;
        LL p,q,r;
        LL x,y;
        cin>>n>>m>>x>>y;
        seg_tree<LL> seg(op,-INF,2*m+2),seg2(op,-INF,2*m+2);
        vector<seg_tree<LL>> vse(3,seg_tree<LL>(op,-INF,2*m+2));
        vector<LL> va;
        vector<T> vt;
        for(i=0;i<m;i++){
            cin>>c>>a>>b;
            a--,c--;
            va.push_back(a),va.push_back(b);
            vt.push_back({a,b,c});
        }
        Compress com(va);
        for(i=0;i<m;i++){
            tie(a,b,c)=vt[i];
            a=com.id(a),b=com.id(b);
            vt[i]=T(a,b,c);
        }
        sort(vt.begin(),vt.end());
        for(i=0;i<m;i++){
            tie(a,b,c)=vt[i];
            q=com.vec[a],r=com.vec[b];
            p=(r-q)*x;
            p=max(p,seg2.search(0,a+1)+(r-q)*x);
            p=max(p,seg.search(a,b)+q*(x+y)+r*x);
            p=max(p,vse[c].search(a,b)+r*x);
            if(p<seg2.search(b,b+1))continue;
            seg.set(b,p-r*(2*x+y));
            seg2.set(b,p);
            vse[c].set(b,p-r*x);
        }
        cout<<seg2.search()<<endl;
    }
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    sol::solve();
}
accuracy: 0.6976744186046512
time_ms: 280
memory_kb: 75884
final_rank: 18

code_snippet: #include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
#include<cassert>
#include<set>
#include<complex>
#include<numeric>
#include<functional>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long int LL;
typedef pair<int,int> P;
typedef pair<LL,LL> LP;
const LL INF=1LL<<60;
const LL MAX=1e9+7;

void array_show(int *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
    for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
    if(vec_n==-1)vec_n=vec_s.size();
    for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
template<typename T> ostream& operator<<(ostream& os,const vector<T>& v1){
    int n=v1.size();
    for(int i=0;i<n;i++){
        if(i)os<<" ";
        os<<v1[i];
    }
    return os;
}
template<typename T1,typename T2> ostream& operator<<(ostream& os,const pair<T1,T2>& p){
    os<<p.first<<" "<<p.second;
    return os;
}
template<typename T> istream& operator>>(istream& is,vector<T>& v1){
    int n=v1.size();
    for(int i=0;i<n;i++)is>>v1[i];
    return is;
}
template<typename T1,typename T2> istream& operator>>(istream& is,pair<T1,T2>& p){
    is>>p.first>>p.second;
    return is;
}

template <typename T> class seg_tree{
    //monoid
private:
    function<T(T,T)> func;
    T e;
    int N,n=-1;
    vector<T> seg;

    void init(){
        assert(n>=0);
        int i;
        for(i=0;(1<<i)<n;i++);
        N=(1<<i)-1;
        seg.assign(2*(N+1),e);
    }

    void init_reload(){
        for(int i=N-1;i>=0;i--){
            seg[i]=func(seg[2*i+1],seg[2*i+2]);
        }
    }
    
    void update(int pos){
        T a=func(seg[pos*2+1],seg[pos*2+2]);
        if(seg[pos]==a)return;
        seg[pos]=a;
        if(pos==0)return;
        update((pos-1)/2);
    }

public:
    seg_tree(function<T(T,T)> _func,T _e,int _n):func(_func),e(_e),n(_n){
        init();
    }
    seg_tree(function<T(T,T)> _func,T _e,vector<T> vec):func(_func),e(_e){
        n=vec.size();
        init();
        for(int i=0;i<n;i++){
            seg[N+i]=vec[i];
        }
        init_reload();
    }
    seg_tree(function<T(T,T)> _func,T _e,int _n,T a):func(_func),e(_e),n(_n){
        init(e);
        for(int i=0;i<n;i++){
            seg[N+i]=a;
        }
        init_reload();
    }

    int size()const{
        return n;
    }

    void set(int pos,T a){
        assert(pos>=0 && pos<=N);
        pos+=N;
        seg[pos]=a;
        update((pos-1)/2);
    }

    T search(int a,int b,int l,int r,int x){//[a,b) search
        if(a<=l && r<=b)return seg[x];
        int m=(l+r)/2;
        if(b<=m)return search(a,b,l,m,2*x+1);
        if(m<=a)return search(a,b,m,r,2*x+2);
        return func(search(a,m,l,m,2*x+1),search(m,b,m,r,2*x+2));
    }
    T search(int a,int b){
        assert(a<b);
        return search(a,b,0,N+1,0);
    }
    T search(){
        return search(0,size());
    }

    int max_right(function<bool(T)>& g,int pos,int l,int r,int x,T& y){
        //suppose that S is return value, g(func(pos,..,S-1))=true,g(func(pos,..,S))=false
        if(pos<=l && g(func(y,seg[x]))){
            y=func(y,seg[x]);
            return r;
        }
        if(l+1==r)return l;
        int m=(l+r)/2;
        if(pos<m){
            int s=max_right(g,pos,l,m,2*x+1,y);
            if(s<m)return s;
        }
        return max_right(g,pos,m,r,2*x+2,y);
    }
    int max_right(function<bool(T)> g,int pos){
        T y=e;
        int s=max_right(g,pos,0,N+1,0,y);
        return min(s,n);
    }

    int min_left(function<bool(T)>& g,int pos,int l,int r,int x,T& y){
        //suppose that S is return value, g(func(S,..,pos-1))=true,g(func(S-1,..,pos-1))=false
        int s;
        if(r<=pos && g(func(seg[x],y))){
            y=func(seg[x],y);
            return l;
        }
        if(l+1==r)return r;
        int m=(l+r)/2;
        if(m<pos){
            s=min_left(g,pos,m,r,2*x+2,y);
            if(m<s)return s;
        }
        return min_left(g,pos,l,m,2*x+1,y);
    }
    int min_left(function<bool(T)> g,int pos){
        assert(pos>=0);
        if(pos==0)return 0;
        T y=e;
        return min_left(g,pos,0,N+1,0,y);
    }
};

template<typename T> class Compress{
    //Compress<int> ca({5,1,2,3});
    //ca.id(5) //=3
private:
    vector<int> id_perm;//v1 index -> vec index
public:
    vector<T> vec;
    void init(const vector<T>& v1){
        int n=v1.size();
        int i,j;
        id_perm.assign(n,-1);
        vector<pair<T,int>> va;
        for(i=0;i<n;i++){
            va.push_back({v1[i],i});
        }
        sort(va.begin(),va.end());
        vec.clear();
        for(i=0,j=-1;i<n;i++){
            if(vec.empty() || vec.back()!=va[i].first){
                vec.push_back(va[i].first);
                j++;
            }
            id_perm[va[i].second]=j;
        }
    }

    Compress(const vector<T> v1){
        init(v1);
    }

    vector<int> get_id_perm()const{
        return id_perm;
    }

    int id(const T a){
        auto itr=lower_bound(vec.begin(),vec.end(),a);
        assert(itr!=vec.end());//return -1?
        assert(*itr==a);
        return itr-vec.begin();
    }
};

namespace sol{
    typedef tuple<LL,LL,LL> T;
    LL op(LL a,LL b){return max(a,b);}

    void solve(){
        LL n,m;
        int i,j,k;
        LL a,b,c;
        LL p,q,r;
        LL x,y;
        cin>>n>>m>>x>>y;
        seg_tree<LL> seg(op,-INF,2*m),seg2(op,-INF,2*m);
        vector<seg_tree<LL>> vse(3,seg_tree<LL>(op,-INF,2*m));
        vector<LL> va;
        vector<T> vt;
        for(i=0;i<m;i++){
            cin>>c>>a>>b;
            a--,c--;
            va.push_back(a),va.push_back(b);
            vt.push_back({a,b,c});
        }
        Compress com(va);
        for(i=0;i<m;i++){
            tie(a,b,c)=vt[i];
            a=com.id(a),b=com.id(b);
            vt[i]=T(a,b,c);
        }
        sort(vt.begin(),vt.end());
        for(i=0;i<m;i++){
            tie(a,b,c)=vt[i];
            q=com.vec[a],r=com.vec[b];
            p=(r-q)*x;
            p=max(p,seg2.search(0,a+1)+(r-q)*x);
            p=max(p,seg.search(a,b)+q*(x+y)+r*x);
            p=max(p,vse[c].search(a,b)+r*x);
            if(p<seg2.search(b,b+1))continue;
            seg.set(b,p-r*(2*x+y));
            seg2.set(b,p);
            vse[c].set(b,p-r*x);
        }
        cout<<seg2.search()<<endl;
    }
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    sol::solve();
}
accuracy: 0.6976744186046512
time_ms: 270
memory_kb: 75912
final_rank: 17

code_snippet: #include <bits/stdc++.h>

using i64 = long long;

constexpr i64 inf = 1E18;

struct Max {
    i64 x = -inf;
};

Max operator+(const Max &a, const Max &b) {
    return {std::max(a.x, b.x)};
}

template<class Info,
    class Merge = std::plus<Info>>
struct SegmentTree {
    const int n;
    const Merge merge;
    std::vector<Info> info;
    SegmentTree(int n) : n(n), merge(Merge()), info(4 << std::__lg(n)) {}
    SegmentTree(std::vector<Info> init) : SegmentTree(init.size()) {
        std::function<void(int, int, int)> build = [&](int p, int l, int r) {
            if (r - l == 1) {
                info[p] = init[l];
                return;
            }
            int m = (l + r) / 2;
            build(2 * p, l, m);
            build(2 * p + 1, m, r);
            pull(p);
        };
        build(1, 0, n);
    }
    void pull(int p) {
        info[p] = merge(info[2 * p], info[2 * p + 1]);
    }
    void modify(int p, int l, int r, int x, const Info &v) {
        if (r - l == 1) {
            info[p] = info[p] + v;
            return;
        }
        int m = (l + r) / 2;
        if (x < m) {
            modify(2 * p, l, m, x, v);
        } else {
            modify(2 * p + 1, m, r, x, v);
        }
        pull(p);
    }
    void modify(int p, const Info &v) {
        modify(1, 0, n, p, v);
    }
    Info rangeQuery(int p, int l, int r, int x, int y) {
        if (l >= y || r <= x) {
            return Info();
        }
        if (l >= x && r <= y) {
            return info[p];
        }
        int m = (l + r) / 2;
        return merge(rangeQuery(2 * p, l, m, x, y), rangeQuery(2 * p + 1, m, r, x, y));
    }
    Info rangeQuery(int l, int r) {
        return rangeQuery(1, 0, n, l, r);
    }
};


int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int n, m, x, y;
    std::cin >> n >> m >> x >> y;
    
    int c[m], l[m], r[m];
    for (int i = 0; i < m; i++) {
        std::cin >> c[i] >> l[i] >> r[i];
        l[i]--;
        c[i]--;
    }
    
    i64 res = 0;
    
    int v[2 * m];
    for (int i = 0; i < m; i++) {
        v[2 * i] = l[i];
        v[2 * i + 1] = r[i];
    }
    
    std::sort(v, v + 2 * m);
    
    int ids[m];
    std::iota(ids, ids + m, 0);
    std::sort(ids, ids + m, [&](int i, int j) { return l[i] < l[j]; });
    
    SegmentTree<Max> seg1(2 * m), seg2[]{2 * m, 2 * m, 2 * m}, seg3[]{2 * m, 2 * m, 2 * m};
    seg1.modify(0, {0LL});
    
    for (auto i : ids) {
        int vl = std::lower_bound(v, v + 2 * m, l[i]) - v;
        int vr = std::lower_bound(v, v + 2 * m, r[i]) - v;
        i64 f = seg1.rangeQuery(0, vl + 1).x + 1LL * x * (r[i] - l[i]);
        for (int u = 0; u < 3; u++) {
            if (u == c[i]) {
                f = std::max(f, seg2[u].rangeQuery(vl, vr).x + 1LL * x * r[i]);
            } else {
                f = std::max(f, seg3[u].rangeQuery(vl, vr).x + 1LL * x * r[i] + 1LL * (x + y) * l[i]);
            }
        }
        seg1.modify(vr, {f});
        seg2[c[i]].modify(vr, {f - 1LL * x * r[i]});
        seg3[c[i]].modify(vr, {f - 1LL * (2 * x + y) * r[i]});
        res = std::max(res, f);
    }
    
    std::cout << res << "\n";
    
    return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 65296
final_rank: 6

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
//#include <atcoder/all>
using namespace std;
//using namespace atcoder;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vector<ll>> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30) - 1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
const int mod = 1e9 + 7;
//const int mod = 998244353;

template<typename Monoid>
struct Segtree {
    using F = function<Monoid(Monoid, Monoid)>;
    int sz;
    vector<Monoid> seg;
    const F f;
    const Monoid M;

    Segtree(int n, const F f, const Monoid &M) : f(f), M(M){
        sz = 1;
        while(sz < n) sz <<= 1;
        seg.assign(2*sz, M);
    }

    void set(int k, const Monoid &x) {
        seg[k + sz] = x;
    }

    void build(){
        for(int k=sz-1; k>0; k--){
            seg[k] = f(seg[2*k], seg[2*k+1]);
        }
    }

    void update(int k, const Monoid x){
        k += sz;
        if(seg[k] == f(seg[k], x)) return;
        seg[k] = x;
        while(k >>= 1){
            seg[k] = f(seg[2*k], seg[2*k+1]);
        }
    }

    Monoid query(int a, int b){
        Monoid L = M, R = M;
        for(a += sz, b += sz; a < b; a >>= 1, b >>= 1){
            if(a & 1) L = f(L, seg[a++]);
            if(b & 1) R = f(seg[--b], R);
        }
        return f(L, R);
    }

    Monoid operator[](const int &k) const {
        return seg[k + sz];
    }

    template<typename C>
    int find_subtree(int a, const C &check, Monoid &M0, bool type){
        while(a < sz){
            Monoid nxt = type ? f(seg[2*a+type],M0) : f(M0,seg[2*a+type]);
            if(check(nxt)) a = 2 * a + type;
            else M0 = nxt, a = 2 * a + 1 - type;
        }
        return a - sz;
    }

    template<typename C>
    int find_first(int a, const C &check){
        Monoid L = M;
        if(a <= 0){
            if(check(f(L, seg[1]))) return find_subtree(1,check,L,false);
            return -1;
        }
        int b = sz;
        for(a += sz, b += sz; a < b; a >>= 1, b >>= 1){
            if(a & 1){
                Monoid nxt = f(L, seg[a]);
                if(check(nxt)) return find_subtree(a,check,L,false);
                L = nxt;
                ++a;
            }
        }
        return -1;
    }

    template<typename C>
    int find_last(int b, const C &check){
        Monoid R = M;
        if(b >= sz){
            if(check(f(seg[1], R))) return find_subtree(1,check,R,true);
            return -1;
        }
        int a = sz;
        for(b += sz; a < b; a >>= 1, b >>= 1){
            if(b & 1){
                Monoid nxt = f(seg[--b], R);
                if(check(nxt)) return find_subtree(b,check,R,true);
                R = nxt;
            }
        }
        return -1;
    }
};

struct rob{
    int c,l,r;
    bool operator< (const rob &ro) const {
        return l < ro.l;
    }
};

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    ll n,m,x,y; cin >> n >> m >> x >> y;
    vector<rob> v(m);
    rep(i,m){
        int c,l,r; cin >> c >> l >> r; c--;
        v[i] = {c,l,r};
    }
    sort(all(v));
    vl rs(m+1,0);
    rep(i,m) rs[i+1] = v[i].r;
    sort(all(rs));
    vector<Segtree<ll>> dp(9,Segtree<ll>(m+1,[](ll a, ll b){return max(a,b);},-linf));
    //dp[0(mod 3)] -> dp, dp[1(mod 3)] -> dp - x, dp[2(mod 3)] -> dp - x*2 - y
    rep(i,9) dp[i].update(0,0);
    rep(i,m){
        int lid = lower_bound(all(rs), v[i].l) - rs.begin();
        int rid = lower_bound(all(rs), v[i].r) - rs.begin();
        ll res = -linf;
        rep(j,3) chmax(res, dp[j*3].query(0,lid) + x*(v[i].r-v[i].l+1));
        rep(j,3){
            if(j == v[i].c){
                chmax(res, dp[j*3+1].query(lid,rid) + x*v[i].r);
            }else{
                chmax(res, dp[j*3+2].query(lid,rid) + x*v[i].r + (x+y)*(v[i].l-1));
            }
        }
        dp[v[i].c*3].update(rid,res);
        dp[v[i].c*3+1].update(rid,res-x*v[i].r);
        dp[v[i].c*3+2].update(rid,res-(x*2+y)*v[i].r);
    }
    ll ans = 0;
    rep(i,3) chmax(ans, dp[i*3].query(0,m+1));
    cout << ans << "\n";
}
accuracy: 1
time_ms: 340
memory_kb: 47764
final_rank: 4

code_snippet: //Let's join Kaede Takagaki Fan Club !!
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
//#define int long long
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define a first
#define b second
#define fi first
#define sc second
#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
#define all(x) x.begin(),x.end()
#define si(x) int(x.size())

#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> bool chmax(t&a,u b){if(a<b){a=b;return true;}else return false;}
template<class t,class u> bool chmin(t&a,u b){if(b<a){a=b;return true;}else return false;}

template<class t> using vc=vector<t>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.fi<<","<<p.sc<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

template<class T>
void g(T &a){
	cin >> a;
}
template<class T>
void o(const T &a,bool space=false){
	cout << a << (space?' ':'\n');
}
//ios::sync_with_stdio(false);
const ll mod = 1000000007;//998244353
mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());
template<class T>
void add(T&a,T b){
	a+=b;
	if(a >= mod) a-=mod;
}
ll modpow(ll x,ll n){
	ll res=1;
	while(n>0){
		if(n&1) res=res*x%mod;
		x=x*x%mod;
		n>>=1;
	}
	return res;
}


struct seg{
	#define sz (1<<19)
	ll seg[sz*2];
	void init(){
		fill(seg, seg + sz*2, -1e18);
	}
	void update(int pos, ll val){
		pos += sz-1;
		seg[pos] = max(seg[pos], val);
		
		while(pos){
			pos = (pos - 1) / 2;
			seg[pos] = max(seg[pos * 2 + 1], seg[pos * 2 + 2]);
		}
	}
	ll query(int a, int b, int k, int l, int r){
		if(r < a || b < l || a > b) return -1e18;
		if(a <= l && r <= b) return seg[k];
		ll lx = query(a, b, k*2+1, l, (l+r)/2);
		ll rx = query(a, b, k*2+2, (l+r)/2+1, r);
		return max(lx, rx);
	}
	ll query(int a, int b){ return query(a, b, 0, 0, sz-1); }
}fr, L[3], R[3];

ll m, x, y, le[200005], ri[200005];
int n, col[200005];
vc<ll>za;
ll dp[200005];
vc<int>query[400005];
void solve(){
	cin >> m >> n >> x >> y;
	repn(i, n){
		cin >> col[i] >> le[i] >> ri[i];
		za.pb(le[i]);
		za.pb(ri[i]+1);
		col[i] --;
	}
	za.pb(-1);
	za.pb(1);
	za.pb(m+1);
	SORT(za); ERASE(za);
	
	fr.init();
	rep(i, 3){
		L[i].init();
		R[i].init();
	}
	repn(i, n){
		query[POSL(za, le[i])].pb(i);
	}
	fr.update(0, 0);
	for(int i=0;i<za.size();i++){
		for(auto at:query[i]){
			dp[at] = -1e18;
			//disjoint
			int p = POSL(za, le[at]);
			int q = POSL(za, ri[at] + 1); q--;
			chmax(dp[at], fr.query(0, p-1) + (ri[at] - le[at] + 1) * x);
			//same col
			chmax(dp[at], L[col[at]].query(p, q-1) + (ri[at]) * x);
			//dif col
			rep(C, 3){
				if(C == col[at]) continue;
				chmax(dp[at], R[C].query(p, q-1) - (-le[at] + 1) * (x+y) + (ri[at]) * x);
			}
		}
		for(auto at:query[i]){
			int p = POSL(za, le[at]);
			int q = POSL(za, ri[at] + 1); q--;
			fr.update(q, dp[at]);
			R[col[at]].update(q, dp[at] - (ri[at]) * (x+y) - (ri[at]) * x);
			L[col[at]].update(q, dp[at] - ri[at] * x);
		}
	}
	cout << fr.query(0, sz-1) << '\n';
}
signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);
	int t; t = 1; //cin >> t;
	while(t--) solve();
}
accuracy: 1
time_ms: 500
memory_kb: 84504
final_rank: 12

code_snippet: #include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<unordered_map>
#include<stack>
#include<string>
#include<algorithm>
#include<functional>
#include<cstring>
#include<complex>
#include<bitset>
#include<iostream>
#include<cassert>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
typedef pair<ll, P> Q;
typedef complex<double> C;
#define cx real()
#define cy imag()
const ll INF = 1LL << 60;
const double DINF = 1e30;
const ll mod = 1000000007;
const ll dx[4] = {1, 0, -1, 0};
const ll dy[4] = {0, -1, 0, 1};
const C I = C(0, 1);
const double EPS = 1e-10;
const ll NCK_MAX = 510000;

ll gcd(ll a, ll b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}

ll extgcd(ll a, ll b, ll& x, ll& y) {
  if (b == 0) {
    x = 1, y = 0; return a;
  }
  ll q = a/b, g = extgcd(b, a - q*b, x, y);
  ll z = x - q * y;
  x = y;
  y = z;
  return g;
}

ll invmod (ll a, ll m) { // a^-1 mod m
  ll x, y;
  extgcd(a, m, x, y);
  x %= m;
  if (x < 0) x += m;
  return x;
}

ll *fac, *finv, *inv;

void nCk_init(ll mod) {
  fac = new ll[NCK_MAX];
  finv = new ll[NCK_MAX];
  inv = new ll[NCK_MAX];
  fac[0] = fac[1] = 1;
  finv[0] = finv[1] = 1;
  inv[1] = 1;
  for (ll i = 2; i < NCK_MAX; i++) {
    fac[i] = fac[i-1] * i % mod;
    inv[i] = mod - inv[mod%i] * (mod / i) % mod;
    finv[i] = finv[i-1] * inv[i] % mod;
  }
}

ll nCk(ll n, ll k, ll mod) {
  if (fac == NULL) nCk_init(mod);
  if (n < k) return 0;
  if (n < 0 || k < 0) return 0;
  return fac[n] * (finv[k] * finv[n-k] % mod) % mod;
}

template <typename T>
class Zip {
  vector<T> d;
  bool flag;
  void init() {
    sort(d.begin(), d.end());
    d.erase(unique(d.begin(), d.end()), d.end());
    flag = false;
  }
public:
  Zip() {
    flag = false;
  }
  void add(T x) {
    d.push_back(x);
    flag = true;
  }
  ll getNum(T x) {
    if (flag) init();
    return lower_bound(d.begin(), d.end(), x) - d.begin();
  }
  ll size() {
    if (flag) init();
    return (ll)d.size();
  }
};

class UnionFind {
  vector<ll> par, rank; // par > 0: number, par < 0: -par
public:
  UnionFind(ll n) : par(n, 1), rank(n, 0) {}
  ll getSize(ll x) {
    return par[find(x)];
  }
  ll find(ll x) {
    if (par[x] > 0) return x;
    return -(par[x] = -find(-par[x]));
  }
  void merge(ll x, ll y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) {
      par[y] += par[x];
      par[x] = -y;
    } else {
      par[x] += par[y];
      par[y] = -x;
      if (rank[x] == rank[y]) rank[x]++;
    }
  }
  bool isSame(ll x, ll y) {
    return find(x) == find(y);
  }
};


template <typename T>
class SegmentTree {
  ll n;
  vector<T> node;
  function<T(T, T)> fun, fun2;
  bool customChange;
  T outValue, initValue;
public:
  void init(ll num, function<T(T, T)> resultFunction, T init, T out, function<T(T, T)> changeFunction = NULL) {
    // changeFunction: (input, beforevalue) => newvalue
    fun = resultFunction;
    fun2 = changeFunction;
    customChange = changeFunction != NULL;
    n = 1;
    while (n < num) n *= 2;
    node.resize(2 * n - 1);
    fill(node.begin(), node.end(), init);
    outValue = out;
    initValue = init;
  }
  void valueChange(ll num, T value) {
    num += n-1;
    if (customChange) node[num] = fun2(value, node[num]);
    else node[num] = value;
    while (num > 0) num = (num - 1) / 2, node[num] = fun(node[num * 2 + 1], node[num * 2 + 2]);
  }
  T rangeQuery(ll a, ll b, ll l = 0, ll r = -1, ll k = 0) { // [a, b)
    if (r == -1) r = n;
    if (a <= l && r <= b) return node[k];
    if (b <= l || r <= a) return outValue;
    ll mid = (l + r) / 2;
    return fun(rangeQuery(a, b, l, mid, 2*k+1), rangeQuery(a, b, mid, r, 2*k+2));
  }
};

template <typename T>
class Graph {
  struct edge { ll to; T cost; };
  struct edge_data { ll from, to; T cost; };

  ll v;
  vector<vector<edge>> e, re;
  vector<edge_data> ed;
  vector<bool> used;
  vector<ll> vs, cmp;
  bool isDirected, isMinasEdge;
public:
  Graph(ll _v, bool _isDirected = true, ll range_add = 0) {
    // range_add 0:no / 1:in / 2:out / 3:in+out
    //_v++;
    v = _v, isDirected = _isDirected; isMinasEdge = false;
    e.resize(v), re.resize(v);
  }
  void add_edge(ll s, ll t, T cost = 1) {
    e[s].push_back((edge){t, cost});
    if (!isDirected) e[t].push_back((edge){s, cost});
    else re[t].push_back((edge){s, cost});
    ed.push_back((edge_data){s, t, cost});
    if (cost < 0) isMinasEdge = true;
  }
  vector<T> dijkstra(ll s) {
    vector<T> d(v, INF);
    d[s] = 0;
    auto edge_cmp = [](const edge& a, const edge& b) { return a.cost > b.cost; };
    priority_queue<edge, vector<edge>, decltype(edge_cmp)> pq(edge_cmp);
    pq.push((edge){s, 0});
    while (!pq.empty()) {
      edge temp = pq.top(); pq.pop();
      if (d[temp.to] < temp.cost) continue;
      for (const edge& next : e[temp.to]) {
        T cost = temp.cost + next.cost;
        if (d[next.to] > cost) {
          d[next.to] = cost;
          pq.push((edge){next.to, cost});
        }
      }
    }
    return d;
  }
  vector<T> bellmanford(ll s) {
    vector<T> d(v, INF);
    d[s] = 0;
    for (ll i = 0; i < v; i++) {
      for (const edge_data& temp : ed) {
        if (d[temp.from] != INF && d[temp.to] > d[temp.from] + temp.cost) d[temp.to] = d[temp.from] + temp.cost;
        if (!isDirected && d[temp.to] != INF && d[temp.from] > d[temp.to] + temp.cost) d[temp.from] = d[temp.to] + temp.cost;
      }
    }
    for (ll i = 0; i < v; i++) {
      for (const edge_data& temp : ed) {
        if (d[temp.from] != INF && d[temp.to] > d[temp.from] + temp.cost) d[temp.to] = -INF;
        if (!isDirected && d[temp.to] != INF && d[temp.from] > d[temp.to] + temp.cost) d[temp.from] = -INF;
      }
    }
    return d;
  }
  vector<T> shortest_path(ll s) {
    if (isMinasEdge) return bellmanford(s);
    else return dijkstra(s);
  }
  T kruskal() {
    // if (isDirected)
    UnionFind uf(v);
    auto edge_data_cmp = [](const edge_data& a, const edge_data& b) { return a.cost < b.cost; };
    sort(ed.begin(), ed.end(), edge_data_cmp);
    T ans = 0;
    for (const edge_data& temp : ed) {
      if (uf.isSame(temp.from, temp.to)) continue;
      uf.merge(temp.from, temp.to);
      ans += temp.cost;
    }
    return ans;
  }
  void scc_dfs(ll s) {
    used[s] = true;
    for (const edge& i : e[s]) if (!used[i.to]) scc_dfs(i.to);
    vs.push_back(s);
  }
  void scc_rdfs(ll s, ll k) {
    used[s] = true;
    cmp[s] = k;
    for (const edge& i : re[s]) if (!used[i.to]) scc_rdfs(i.to, k);
  }
  vector<ll> scc() {
    used.resize(v);
    fill(used.begin(), used.end(), false);
    cmp.resize(v);
    vs.clear();
    for (ll i = 0; i < v; i++) if (!used[i]) scc_dfs(i);
    used.resize(v);
    fill(used.begin(), used.end(), false);
    ll k = 0;
    for (ll i = vs.size() - 1; i >= 0; i--) if (!used[vs[i]]) scc_rdfs(vs[i], k++);
    return cmp;
  }
};

class RollingHash {
  int base;
  vector<__int128> hash;
  vector<__int128> pw;
  const __int128 hashmod = (1ull << 61) - 1;
public:
  RollingHash(string s, int base = 10007) : base(base), hash(s.length()+1, 0), pw(s.length()+1, 1) {
    for (int i = 0; i < (int)s.length(); i++) {
      hash[i+1] = (hash[i] * base + s[i]) % hashmod;
      pw[i+1] = pw[i] * base % hashmod;
    }
  }
  ll get(ll a, ll b) { // [a, b)
    __int128 tmp = hashmod + hash[b] - hash[a] * pw[b-a] % hashmod;
    if (tmp >= hashmod) tmp -= hashmod;
    return (ll)tmp;
  }
};

ll n, m, x, y, c, l, r;
Q q[200000];

ll mx(ll a, ll b) { return max(a, b); }

int main() {
  scanf("%lld%lld%lld%lld", &n, &m, &x, &y);
  Zip<ll> zip;
  for (ll i = 0; i < m; i++) {
    scanf("%lld%lld%lld", &c, &l, &r);
    c--;
    q[i] = Q(l, P(c, r));
    zip.add(l);
    zip.add(r);
  }
  zip.add(0);
  n = zip.size();
  sort(q, q+m);
  SegmentTree<ll> dp, dp2[3], dp3[3];
  dp.init(n+1, mx, -INF, -INF);
  for (ll i = 0; i < 3; i++) dp2[i].init(n+1, mx, -INF, -INF);
  for (ll i = 0; i < 3; i++) dp3[i].init(n+1, mx, -INF, -INF);
  dp.valueChange(0, 0);
  for (ll i = 0; i < m; i++) {
    l = q[i].first, c = q[i].second.first, r = q[i].second.second;
    ll l2 = zip.getNum(l), r2 = zip.getNum(r);
    ll tmp = dp.rangeQuery(0, l2) + (r - l + 1) * x;
    for (ll j = 0; j < 3; j++) {
      if (j == c) {
        tmp = max(tmp, dp2[j].rangeQuery(l2, r2) + r * x);
      } else {
        tmp = max(tmp, dp3[j].rangeQuery(l2, r2) + r * x + (l-1) * (x+y));
      }
    }
    if (dp.rangeQuery(r2, r2+1) < tmp) dp.valueChange(r2, tmp);
    tmp -= r * x;
    if (dp2[c].rangeQuery(r2, r2+1) < tmp) dp2[c].valueChange(r2, tmp);
    tmp -= r * (x+y);
    if (dp3[c].rangeQuery(r2, r2+1) < tmp) dp3[c].valueChange(r2, tmp);
  }
  printf("%lld\n", dp.rangeQuery(0, n+1));
}
accuracy: 1
time_ms: 600
memory_kb: 68208
final_rank: 11