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

template <typename T>
struct Dijkstra {
    struct Edge {
        int to;
        T cost;
    };

    vector<int> prev;
    vector<vector<Edge>> g;

    Dijkstra(int n) : prev(n, -1), g(n) {}

    void add_edge(int u, int v, T w) { g[u].push_back({v, w}); }
    vector<T> build(int s) {
        using Node = pair<T, int>;
        vector<T> dist(g.size(), -1);
        priority_queue<Node, vector<Node>, greater<Node>> pq;
        pq.push({dist[s] = 0, s});
        while (!pq.empty()) {
            T d = pq.top().first;
            int u = pq.top().second;
            pq.pop();
            if (dist[u] < d) continue;
            for (auto&& v : g[u]) {
                if (dist[v.to] < 0 || dist[v.to] > dist[u] + v.cost) {
                    pq.push({dist[v.to] = dist[u] + v.cost, v.to});
                    prev[v.to] = u;
                }
            }
        }
        return dist;
    }
    vector<int> get_path(int t) {
        vector<int> path;
        for (int i = t; i != -1; i = prev[i]) path.push_back(i);
        reverse(begin(path), end(path));
        return path;
    }
};

int main() {
    int a, b, x, y;
    cin >> a >> b >> x >> y;
    a--;
    b--;
    Dijkstra<int> g(200);
    for (int i = 0; i < 100; i++) {
        g.add_edge(i, i + 100, x);
        g.add_edge(i + 100, i, x);
    }
    for (int i = 0; i < 99; i++) {
        g.add_edge(i + 1, i + 100, x);
        g.add_edge(i + 100, i + 1, x);
        g.add_edge(i, i + 1, y);
        g.add_edge(i + 1, i, y);
        g.add_edge(i + 100, i + 101, y);
        g.add_edge(i + 101, i + 100, y);
    }
    auto d = g.build(a);
    cout << d[b + 100] << endl;
}
#include <cstdio>
#include <iostream>
#include <cassert>
#include <string>
#include <algorithm>
#include <cstring>
#include <utility>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <unordered_map>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0)

using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> order_set;

bool check(auto &light, auto &grid, int i, int j, bool OK) {
    if (grid[i][j] == 0) OK = false;
    else if (grid[i][j] == 1) OK = true;
    light[i][j] |= OK;
    return OK;
}

int main() {
    int H, W, N, M;
    scanf("%d %d %d %d", &H, &W, &N, &M);
    vector<vector<int>> grid(H, vector<int>(W, -1));
    vector<vector<int>> light(H, vector<int>(W, 0));
    for (int i = 0; i < N; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        a--, b--;
        grid[a][b] = 1;
    }
    for (int i = 0; i < M; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        a--, b--;
        grid[a][b] = 0;
    }
    for (int i = 0; i < H; i++) {
        bool OK = false;
        for (int j = 0; j < W; j++)
            OK = check(light, grid, i, j, OK);
        OK = false;
        for (int j = W - 1; j >= 0; j--)
            OK = check(light, grid, i, j, OK);
    }
    for (int c = 0; c < W; c++) {
        bool OK = false;
        for (int r = 0; r < H; r++)
            OK = check(light, grid, r, c, OK);
        OK = false;
        for (int r = H - 1; r >= 0; r--)
            OK = check(light, grid, r, c, OK);
    }
    int ans = 0;
    for (int i = 0; i < H; i++)
        for (int j = 0; j < W; j++) {
            ans += light[i][j];
            //printf("i = %d j = %d l = %d\n", i, j, light[i][j]);
        }
    printf("%d\n", ans);
    return 0;
}
/* stuff you should look for
	* int overflow, array bounds
	* special cases (n=1?)
	* do smth instead of nothing and stay organized
	* WRITE STUFF DOWN
by Benq;
*/
