#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
using namespace std;
using namespace __gnu_pbds;
#define int long long
#define f first
#define s second
#define pll pair<long long, long long>
#define pb push_back
#define all(x) x.begin(), x.end()
const long long INF = (long long)4e18;
/*
This is the LineContainer from OI notes, max-query version.
To query minimum of y = mx + c:
insert (-m, -c)
answer = -query(x)
*/
struct Line {
mutable long long k, m, p; // y = kx + m, p = last x where this line is best
bool operator<(const Line& o) const {
return k < o.k;
}
bool operator<(long long x) const {
return p < x;
}
};
struct LineContainer : multiset<Line, less<>> {
static const long long inf = LLONG_MAX;
long long div_floor(long long a, long long b) {
// floored division
long long q = a / b;
long long r = a % b;
if ((a ^ b) < 0 && r) q--;
return q;
}
bool isect(iterator x, iterator y) {
if (y == end()) {
x->p = inf;
return false;
}
if (x->k == y->k) {
x->p = (x->m > y->m ? inf : -inf);
} else {
x->p = div_floor(y->m - x->m, x->k - y->k);
}
return x->p >= y->p;
}
void add_line(long long k, long long m) {
auto z = insert({k, m, 0});
auto y = z++;
auto x = y;
while (isect(y, z)) z = erase(z);
if (x != begin() && isect(--x, y)) {
isect(x, y = erase(y));
}
while ((y = x) != begin() && (--x)->p >= y->p) {
isect(x, erase(y));
}
}
long long query_max(long long x) {
assert(!empty());
auto l = *lower_bound(x);
return l.k * x + l.m;
}
void add_min_line(long long k, long long m) {
add_line(-k, -m);
}
long long query_min(long long x) {
return -query_max(x);
}
};
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int X, N, M, W, T;
cin >> X >> N >> M >> W >> T;
vector<pll> events; // {residue, quotient}
for (int i = 0; i < N; i++) {
int S;
cin >> S;
events.pb({S % T, S / T});
}
// Treat destination X as a "final refill event":
// passengers may fail before arrival, but driver must survive.
events.pb({X % T, X / T});
vector<pll> p(M + 1); // {D, C}, 1-indexed after sorting
for (int i = 1; i <= M; i++) {
cin >> p[i].f >> p[i].s;
}
sort(p.begin() + 1, p.end());
vector<int> prefC(M + 1, 0);
for (int i = 1; i <= M; i++) {
prefC[i] = prefC[i - 1] + p[i].s;
}
// We process passengers from right to left by D.
// So process refill/end events from large residue to small residue.
sort(events.begin(), events.end(), greater<pll>());
vector<int> dp(M + 2, INF);
dp[M + 1] = 0;
LineContainer cht;
int ptr = 0;
for (int i = M; i >= 1; i--) {
int D = p[i].f;
/*
Insert every refill/end event with residue > D.
Suppose this event is S = qT + r, and currently it lies between
passenger i and i+1 in sorted D-order.
Let b = i. If later we choose passengers a..b to leave before this event:
cost = dp[b+1]
+ (prefC[b] - prefC[a-1])
+ (b-a+1) * q * W
Rearrange by a:
cost = -prefC[a-1]
+ (-qW) * a
+ (dp[b+1] + prefC[b] + qW*(b+1))
So this event contributes one line:
y = (-qW)x + (dp[b+1] + prefC[b] + qW*(b+1))
*/
while (ptr < (int)events.size() && events[ptr].f > D) {
int q = events[ptr].s;
int b = i;
int slope = -q * W;
int intercept = dp[b + 1] + prefC[b] + q * W * (b + 1);
cht.add_min_line(slope, intercept);
ptr++;
}
// Option 1: passenger i reaches destination.
int full_drinks = X / T + (X % T > D);
dp[i] = dp[i + 1] + full_drinks * W;
// Option 2: passenger i is the start of a block that leaves before some event.
if (!cht.empty()) {
dp[i] = min(dp[i], cht.query_min(i) - prefC[i - 1]);
}
}
// Driver drinks at times 0, T, 2T, ..., floor(X/T)T.
int driver_cost = (X / T + 1) * W;
cout << dp[1] + driver_cost << '\n';
}