#include <bits/stdc++.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=int(a)-1;i>=int(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)

#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))
#define popcount(n) (__builtin_popcountll(n))

using namespace std;

template<class T>bool chmax(T &a, const T &b) { return (a<b)?(a=b,1):0;}
template<class T>bool chmin(T &a, const T &b) { return (b<a)?(a=b,1):0;}

using ll=long long;
const int nmax=300010;
using P=tuple<ll,ll>;

struct Segment_tree{

	using T=ll; using U=ll;
	int n,h;
	vector<T> data; vector<U> lazy;
	const T out_t=0; const U out_u=0;

	Segment_tree(int m){n=m,h=32-__builtin_clz(n),data.assign(2*n,out_t),lazy.assign(n,out_u);}

	// data merge
	T vmerge(T l,T r){ return max(l,r);}
	
	// lazy_evaluation
	void apply(int p, U v){
		data[p]+=v;
		if(p < n) lazy[p] += v;
	}

	void push(int p){
		for(int s = h; s > 0; --s) {
			int i = p >> s;
			if(lazy[i] != out_u){
				apply(i<<1,  lazy[i]),apply(i<<1|1,lazy[i]);
				lazy[i] = out_u;
				data[i]=vmerge(data[i<<1],data[i<<1|1]);
			}
		}
	}

	void build(int p) {
		while (p > 1) p >>= 1, data[p] = vmerge(data[p<<1], data[p<<1|1]) + lazy[p];
	}


	void update(int l, int r,T v){
		l += n, r += n;
		int l0 = l, r0 = r;
		for (; l < r; l >>= 1, r >>= 1) {
			if(l&1) apply(l++, v);
			if(r&1) apply(--r, v);
		}
		build(l0),build(r0 - 1);
	}

	T query(int l, int r) {
		l += n, r += n;
		push(l),push(r-1);
		T resl =out_t,resr=out_t;
		for (; l < r; l >>= 1, r >>= 1) {
			if (l&1) resl = vmerge(data[l++],resl);
			if (r&1) resr = vmerge(resr,data[--r]);
		}
		return vmerge(resl,resr);
	}
};


ll solve(vector<P> &ary,ll w,ll h){
	ll ret=0LL;
	sort(_all(ary));
	ary.push_back(P(h,0));
	const int n=int(ary.size());
	
	
	stack<P> lft,rht;
	lft.push(P(0LL,w/2LL));
	rht.push(P(0LL,w/2LL));

	vector<ll> yary={0LL,h};
	rep(i,n) yary.push_back(get<0>(ary[i]));
	uniq(yary);

	const int m=yary.size();

	auto getidx=[&](ll arg){
		return lower_bound(_all(yary),arg)-begin(yary);
	};

	
	Segment_tree seg(m);
	rep(i,m) seg.update(i,i+1,-yary[i]);
	seg.update(0,m,w);

	//cout << "OK" << endl;


	rep(i,n){
		ll y,x;
		tie(y,x)=ary[i];
		chmax(ret,seg.query(0,getidx(y))+y);
		//cout << getidx(y) << endl;
		//cout << y << " " << x << " " << seg.query(0,getidx(y)) << " " << seg.query(0,getidx(y))+y << endl;

		if(x<=w/2){
			ll px=0,py=y;
			while(!lft.empty() and get<1>(lft.top()) < x){
				seg.update(getidx(get<0>(lft.top())),getidx(py),px-x);
				tie(py,px)=lft.top();
				lft.pop();
			}
			seg.update(getidx(get<0>(lft.top())),getidx(py),px-x);
			//cout << y << " " << x << " " << seg.query(0,getidx(y))  << endl;
			lft.push(P(y,x));
		}else{
			ll px=w,py=y;
			while(!rht.empty() and get<1>(rht.top()) > x){
				seg.update(getidx(get<0>(rht.top())),getidx(py),x-px);
				tie(py,px)=rht.top();
				rht.pop();
			}
			seg.update(getidx(get<0>(rht.top())),getidx(py),x-px);
			rht.push(P(y,x));
		}
	}

	ary.pop_back();
	//cout << "OK" << endl;
	//cout << ret << endl;
	return ret;
}

int main(void){
	ll w,h,n;
	cin >> w >> h >> n;
	w*=2,h*=2;

	vector<P> ary(n);
	rep(i,n){
		cin >> get<1>(ary[i]) >> get<0>(ary[i]);
		get<0>(ary[i])*=2;
		get<1>(ary[i])*=2;
	}
		

	ll wans=solve(ary,w,h);
	
	swap(w,h);
	rep(i,n) swap(get<0>(ary[i]),get<1>(ary[i]));

	ll hans=solve(ary,w,h);
	
	//cout << wans << " " << hans << endl;
	cout << max(wans,hans) << endl;
	return 0;
}

Measured memory_bytes: 16816