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

int maxIndex = 0;
int tree[4000000], treeLeft[4000000], treeRight[4000000];
int lazy[4000000];

int treeOrig[4000000], treeLeftOrig[4000000], treeRightOrig[4000000];

int treeValue(int index) {
    if (lazy[index] > 0) return 0;
    return tree[index];
}

int treeLeftValue(int index) {
    if (lazy[index] > 0) return 0;
    return treeLeft[index];
}

int treeRightValue(int index) {
    if (lazy[index] > 0) return 0;
    return treeRight[index];
}

tuple<int,int,int,int> getValue(int nodeIndex, int nodeLeft, int nodeRight, int left, int right) {
    if (right < nodeLeft || nodeRight < left) return make_tuple(0,0,0,0);
    if (lazy[nodeIndex] != 0) return make_tuple(0, 0, 0, 0);
    if (left <= nodeLeft && nodeRight <= right) {
        return make_tuple(treeValue(nodeIndex), treeLeftValue(nodeIndex), treeRightValue(nodeIndex), nodeRight-nodeLeft+1);
    }
    int mid = (nodeLeft+nodeRight)/2;
    auto ansLeft = getValue(nodeIndex*2, nodeLeft, mid, left, right);
    auto ansRight = getValue(nodeIndex*2+1, mid+1, nodeRight, left, right);
    int ans1 = max(get<0>(ansLeft), get<0>(ansRight));
    ans1 = max(ans1, get<2>(ansLeft)+get<1>(ansRight));
    int ans2 = get<1>(ansLeft);
    if (ans2 == get<3>(ansLeft)) ans2+=get<1>(ansRight);
    int ans3 = get<2>(ansRight);
    if (ans3 == get<3>(ansRight)) ans3+=get<2>(ansLeft);
    int ans4 = get<3>(ansLeft)+get<3>(ansRight);
    return make_tuple(ans1, ans2, ans3, ans4);
}

void setValue(int nodeIndex, int nodeLeft, int nodeRight, int index, int value) {
    maxIndex = max(maxIndex, nodeIndex);
    if (index < nodeLeft || nodeRight < index) return;
    else if (nodeLeft == nodeRight) {
        treeOrig[nodeIndex]=treeLeftOrig[nodeIndex]=treeRightOrig[nodeIndex]=value;
    } else {
        int mid = (nodeLeft+nodeRight)/2;
        setValue(nodeIndex*2, nodeLeft, mid, index, value);
        setValue(nodeIndex*2+1, mid+1, nodeRight, index, value);
        if (treeLeftOrig[nodeIndex*2]==mid-nodeLeft+1) {
            treeLeftOrig[nodeIndex] = treeLeftOrig[nodeIndex*2]+treeLeftOrig[nodeIndex*2+1];
        } else {
            treeLeftOrig[nodeIndex] = treeLeftOrig[nodeIndex*2];
        }
        if (treeRightOrig[nodeIndex*2+1]==nodeRight-mid) {
            treeRightOrig[nodeIndex] = treeRightOrig[nodeIndex*2]+treeRightOrig[nodeIndex*2+1];
        } else {
            treeRightOrig[nodeIndex] = treeRightOrig[nodeIndex*2+1];
        }
        treeOrig[nodeIndex] = max(treeOrig[nodeIndex*2], treeOrig[nodeIndex*2+1]);
        treeOrig[nodeIndex] = max(treeOrig[nodeIndex], treeRightOrig[nodeIndex*2]+treeLeftOrig[nodeIndex*2+1]);
    }
}

void changeValue(int nodeIndex, int nodeLeft, int nodeRight, int rangeStart, int rangeEnd, int update) {
    if (rangeEnd < nodeLeft || nodeRight < rangeStart) {
        return;
    } else if (rangeStart <= nodeLeft && nodeRight <= rangeEnd) {
        lazy[nodeIndex]+=update;
    } else {
        int mid = (nodeLeft+nodeRight)/2;

        changeValue(nodeIndex*2, nodeLeft, mid, rangeStart, rangeEnd, update);
        changeValue(nodeIndex*2+1, mid+1, nodeRight, rangeStart, rangeEnd, update);

        if (treeLeftValue(nodeIndex*2)==mid-nodeLeft+1) {
            treeLeft[nodeIndex] = treeLeftValue(nodeIndex*2)+treeLeftValue(nodeIndex*2+1);
        } else {
            treeLeft[nodeIndex] = treeLeftValue(nodeIndex*2);
        }
        if (treeRightValue(nodeIndex*2+1)==nodeRight-mid) {
            treeRight[nodeIndex] = treeRightValue(nodeIndex*2)+treeRightValue(nodeIndex*2+1);
        } else {
            treeRight[nodeIndex] = treeRightValue(nodeIndex*2+1);
        }
        tree[nodeIndex] = max(treeValue(nodeIndex*2), treeValue(nodeIndex*2+1));
        tree[nodeIndex] = max(tree[nodeIndex], treeRightValue(nodeIndex*2)+treeLeftValue(nodeIndex*2+1));
    }
}

bool rr[1000001], cc[1000001];
vector<pair<int, int>> lines1[1000001], lines2[1000001];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n, m, q; cin >> n >> m >> q;
    rr[n]=1;
    cc[0]=cc[m]=1;
    for (int i = 0; i < q; i++) {
        int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
        if (x1 == x2) {
            rr[x1-1]=1;
            rr[x1]=1;
            if (y1 > y2) swap(y1, y2);
            lines1[x1].push_back({y1, y2});
            lines2[x1].push_back({-y1, -y2});
            cc[y1-1]=1;
            cc[y2]=1;
        } else {
            if (x1 > x2) swap(x1, x2);
            rr[x1-1]=1;
            rr[x1]=1;
            rr[x2]=1;
            lines1[x1].push_back({y1, y2});
            lines2[x2].push_back({-y1, -y2});
            cc[y1-1]=1;
            cc[y2]=1;
        }
    }
    vector<int> rows;
    for (int i = 0; i <= n; i++) if (rr[i]) rows.push_back(i);

    vector<int> cols;
    for (int i = 0; i <= m; i++) if (cc[i]) cols.push_back(i);

    int left = 1, right = min(n, m);
    for (int i = 1; i <= m; i++) setValue(1, 1, m, i, 1);

    while (left <= right) {
        int middle = (left+right)/2;
        for (int i = 1; i <= maxIndex; i++) {
            tree[i] = treeOrig[i];
            treeLeft[i] = treeLeftOrig[i];
            treeRight[i] = treeRightOrig[i];
            lazy[i] = 0;
        }

        int lower = 0;
        bool ok = false;
        for (int rr = 0; rr < rows.size(); rr++) {
            int r = rows[rr];
            if (r > n) break;
            for(int pp = 0; pp < lines1[r].size(); pp++) {
                pair<int, int> p = lines1[r][pp];
                if (p.first >= 0) {
                    changeValue(1, 1, m, p.first, p.second, 1);
                }
            }
            while (rows[lower] < r && r - rows[lower] >= middle) {
                for(int pp = 0; pp < lines2[rows[lower]].size(); pp++) {
                    pair<int, int> p = lines2[rows[lower]][pp];
                    if (p.first < 0) {
                        changeValue(1, 1, m, -p.first, -p.second, -1);
                    }
                }
                lower++;
            }
            if (r >= middle) {
                int val = get<0>(getValue(1, 1, m, 1, m));
                if (val >= middle) {
                    ok = true;
                    break;
                }
            }
        }
        if (ok) left = middle+1;
        else right=middle-1;
    }
    cout << right << endl;

    return 0;
}
