#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>

using namespace std;

const int TSIZE = (1 << 22);

struct point
{
    int x, y;

    point(int _x, int _y)
    {
        x = _x; y = _y;
    }

    bool operator<(point other) const
    {
        return y < other.y || (y == other.y && x < other.x);
    }
};

int n, m;
int tree[TSIZE];

int get_index(int index)
{
    return (TSIZE >> 1) + index;
}

void update(int index, int value)
{
    index = get_index(index);

    tree[index] = value;
    index >>= 1;
    while(index)
    {
        tree[index] = max(tree[index * 2], tree[index * 2 + 1]);
        index >>= 1;
    }
}

int query(int l, int r)
{
    l = get_index(l); r = get_index(r);

    if(l == r)
    {
        return tree[l];
    }
    int ans = max(tree[l], tree[r]);

    while(l + 1 != r)
    {
        if((l & 1) == 0) ans = max(ans, tree[l + 1]);
        if((r & 1) == 1) ans = max(ans, tree[r - 1]);
        l >>= 1; r >>= 1;
    }
    return ans;
}

map < pair <int, int>, bool> marked;

vector <point> v;

void solve()
{
    scanf("%d %d", &n, &m);

    int q;
    scanf("%d", &q);

    //update(1, 0, MAXM, 2, 5, 1);

    //printf("%d\n", query(1, 0, MAXM, 2, 4));
    while(q--)
    {
        int x, y, x1, y1;
        scanf("%d %d %d %d", &x, &y, &x1, &y1);
        if(x == x1)
        {
            for(int i = y; i <= y1; i++)
            {
                if(!marked[{x, i}])
                {
                    v.push_back(point(x, i));
                    marked[{x, i}] = true;
                }
                //marked[get_ind(x, i)] = true;
            }
        }
        else
        {
            for(int i = x; i <= x1; i++)
            {
                if(!marked[{i, y}])
                {
                    v.push_back(point(i, y));
                    marked[{i, y}] = true;
                }
                //marked[get_ind(i, y)] = true;
            }
        }
    }

    for(int i = 1; i <= n; i++)
    {
        v.push_back(point(i, m + 1));
    }

    sort(v.begin(), v.end());

    int ans = 0;

    //update(1, 5);
    //update(2, 6);
    //update(3, 3);

    //printf("%d\n", query(2, 3));

    for(int i = 0; i < v.size(); i++)
    {
        int qr = query(v[i].x, v[i].x);
        int temp = v[i].y - qr - 1;
        update(v[i].x, v[i].y);
        //printf("%d %d %d %d\n", v[i].x, v[i].y, temp, qr);
        int tnp = 1;
        for(int j = v[i].x - 1; j > 0; j--)
        {
            int co = v[i].y - query(j, v[i].x - 1) - 1;
            if(co >= temp)
            {
                tnp++;
            }
            else
            {
                break;
            }
        }
        for(int j = v[i].x + 1; j <= n; j++)
        {
            int co = v[i].y - query(v[i].x + 1, j) - 1;
            if(co >= temp)
            {
                tnp++;
            }
            else
            {
                break;
            }
        }
        int current = min(tnp, temp);
        ans = max(ans, current);
    }
    printf("%d\n", ans);
}

int main()
{
    solve();

    return 0;
}

/*
6 5
4
1 2 1 5
1 4 5 4
5 2 5 2
1 2 1 5
*/
