Problem:
Score : 1600 points

Problem Statement

There is a rectangle in the xy-plane, with its lower left corner at (0, 0) and its upper right corner at (W, H). Each of its sides is parallel to the x-axis or y-axis. Initially, the whole region within the rectangle is painted white.

Snuke plotted N points into the rectangle. The coordinate of the i-th (1 ≦ i ≦ N) point was (x_i, y_i).

Then, for each 1 ≦ i ≦ N, he will paint one of the following four regions black:

the region satisfying x < x_i within the rectangle

the region satisfying x > x_i within the rectangle

the region satisfying y < y_i within the rectangle

the region satisfying y > y_i within the rectangle

Find the longest possible perimeter of the white region of a rectangular shape within the rectangle after he finishes painting.

Constraints

1 ≦ W, H ≦ 10^8

1 ≦ N ≦ 3 \times 10^5

0 ≦ x_i ≦ W (1 ≦ i ≦ N)

0 ≦ y_i ≦ H (1 ≦ i ≦ N)

W, H (21:32, added), x_i and y_i are integers.

If i ≠ j, then x_i ≠ x_j and y_i ≠ y_j.

Input

The input is given from Standard Input in the following format:

W H N
x_1 y_1
x_2 y_2
:
x_N y_N

Output

Print the longest possible perimeter of the white region of a rectangular shape within the rectangle after Snuke finishes painting.

Sample Input 1

10 10 4
1 6
4 1
6 9
9 4

Sample Output 1

32

In this case, the maximum perimeter of 32 can be obtained by painting the rectangle as follows:

Sample Input 2

5 4 5
0 0
1 1
2 2
4 3
5 4

Sample Output 2

12

Sample Input 3

100 100 8
19 33
8 10
52 18
94 2
81 36
88 95
67 83
20 71

Sample Output 3

270

Sample Input 4

100000000 100000000 1
3 4

Sample Output 4

399999994

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

//首先有一个比较重要的性质
//那就是答案矩形一定经过直线x=w/2或直线y=h/2
//因为答案下界是2*(max(h,w)+1)，观察易得。
//然后我们就有一个比较好的n^2做法
//也就是在枚举的L和R之间找 大于h/2且最小的U 与 小于等于h/2且最大的D
//此时的U和D就是L,R作为边界之一时的最优答案
//另一个方向也是这么做。
//考虑增量法更新答案。
//我们不难发现随着R增加，每一个L对应的U是只降不增的，D是只增不降的
//而且随着L的增大，每一个R对应的U和D也有类似的性质
//考虑每次移动R的时候，更新所有L的答案
//那么我们只需要两个单调栈分别维护所有L的U与D。
//然后用线段树区间修改+查询max即可 
//详细看题解+代码 
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define N 300005
using namespace std;
int w,h,n,ans;
struct Point
{
	int x,y;
}p[N];
int cmp1(Point a,Point b)
{
	return a.x<b.x;
}
int cmp2(Point a,Point b)
{
	return a.y<b.y;
}
struct node
{
	int l,r,v;
};
vector<node>st1,st2;
int maxn[4*N],tag[4*N];
inline void Add(int k,int v)
{
	maxn[k]+=v,tag[k]+=v;
}
inline void down(int k)
{
	if(!tag[k])return;
	Add(k*2,tag[k]);
	Add(k*2+1,tag[k]);
	tag[k]=0;
}
void change(int k,int l,int r,int x,int y,int v)
{
	if(x<=l&&r<=y)
	{
		Add(k,v);
		return;
	}
	int mid=(l+r)>>1;
	down(k);
	if(x<=mid)change(k*2,l,mid,x,y,v);
	if(y>mid)change(k*2+1,mid+1,r,x,y,v);
	maxn[k]=max(maxn[k*2],maxn[k*2+1]);
}
int Ask(int k,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)return maxn[k];
	int mid=(l+r)>>1;
	down(k);
	int temp=-1e9;
	if(x<=mid)temp=max(temp,Ask(k*2,l,mid,x,y));
	if(y>mid)temp=max(temp,Ask(k*2+1,mid+1,r,x,y));
	maxn[k]=max(maxn[k*2],maxn[k*2+1]);
	return temp;
}
int main()
{
//	freopen("paint3.in","r",stdin);
	scanf("%d %d %d",&w,&h,&n);
	for(int i=1;i<=n;i++)
		scanf("%d %d",&p[i].x,&p[i].y);
	p[++n]=(Point){0,0};
	p[++n]=(Point){w,h};
	sort(p+1,p+1+n,cmp1);
	for(int i=1;i<=n;i++)
	{
		int maxn=h,minn=0;
		if(p[i].y<=h/2)minn=max(minn,p[i].y);
		else maxn=max(minn,p[i].y);
		while(i<n&&p[i].x==p[i+1].x)
		{
			i++;
			if(p[i].y<=h/2)minn=max(minn,p[i].y);
			else maxn=max(minn,p[i].y);
		}
		if(i!=1)ans=max(ans,p[i].x+Ask(1,1,n,1,i-1));
		change(1,1,n,i,i,-p[i].x+h-0);
		
		int L=i,R=i-1;
		while(!st1.empty()&&st1.back().v>=maxn)
		{
			change(1,1,n,st1.back().l,st1.back().r,-st1.back().v);
			L=st1.back().l;
			st1.pop_back();
		}
		if(L<=R)st1.push_back((node){L,R,maxn}),change(1,1,n,L,R,maxn);
		st1.push_back((node){i,i,h});
		
		L=i,R=i-1;
		while(!st2.empty()&&st2.back().v<=minn)
		{
			change(1,1,n,st2.back().l,st2.back().r,st2.back().v);
			L=st2.back().l;
			st2.pop_back();
		}
		if(L<=R)st2.push_back((node){L,R,minn}),change(1,1,n,L,R,-minn);
		st2.push_back((node){i,i,0});
	}
	memset(tag,0,sizeof(tag));
	memset(maxn,0,sizeof(maxn));
	st1.clear(),st2.clear();
	sort(p+1,p+1+n,cmp2);
	for(int i=1;i<=n;i++)
	{
		int maxn=w,minn=0;
		if(p[i].x<=h/2)minn=max(minn,p[i].x);
		else maxn=max(minn,p[i].x);
		while(i<n&&p[i].y==p[i+1].y)
		{
			i++;
			if(p[i].x<=w/2)minn=max(minn,p[i].x);
			else maxn=max(minn,p[i].x);
		}
		if(i!=1)ans=max(ans,p[i].y+Ask(1,1,n,1,i-1));
		change(1,1,n,i,i,-p[i].y+w-0);
		
		int L=i,R=i-1;
		while(!st1.empty()&&st1.back().v>=maxn)
		{
			change(1,1,n,st1.back().l,st1.back().r,-st1.back().v);
			L=st1.back().l;
			st1.pop_back();
		}
		if(L<=R)st1.push_back((node){L,R,maxn}),change(1,1,n,L,R,maxn);
		st1.push_back((node){i,i,w});
		
		L=i,R=i-1;
		while(!st2.empty()&&st2.back().v<=minn)
		{
			change(1,1,n,st2.back().l,st2.back().r,st2.back().v);
			L=st2.back().l;
			st2.pop_back();
		}
		if(L<=R)st2.push_back((node){L,R,minn}),change(1,1,n,L,R,-minn);
		st2.push_back((node){i,i,0});
	}
	printf("%d\n",2*ans);
	return 0;
}