import std.container;
import std.algorithm;
import std.stdio;
import core.stdc.stdio;
import std.typecons;

struct BinaryIndexedTree{
	int s;
	int[] data;
	void Initialize(int size){
		s=size;
		data = new int[size];
	}
	void Add(int idx,int val){
		while(idx<s){
			data[idx]+=val;
			idx+=(idx+1)&(-idx-1);
		}
	}
	int Get(int idx){
		int ret=0;
		while(idx>=0){
			ret += data[idx];
			idx -= (idx+1)&(-idx-1);
		}
		return ret;
	}
	int Query(int b,int e){
		if(e<=b)
			return 0;
		return Get(e-1)-Get(b-1);
	}
}

struct UnionFind{
	alias Tuple!(int,"rank",int,"parent") rp;
	rp[] data;
	void Initialize(int s){
		data = new rp[s];
		for(int i=0;i<s;i++)
			data[i].parent=i;
	}
	int Find(int idx){
		if(data[idx].parent==idx)
			return idx;
		return data[idx].parent=Find(data[idx].parent);
	}
	int Unify(int a,int b){
		a = Find(a);
		b = Find(b);
		if(a!=b){
			if(data[a].rank<data[b].rank)
				data[a].parent = b;
			else if(data[a].rank>data[b].rank)
				data[b].parent = a;
			else{
				data[a].parent = b;
				data[b].rank++;
			}
			return 1;
		}
		return 0;
	}
}

int LowerBoundIdx(T)(T[] data,T t){
	int l=0;
	int r=cast(int)data.length+1;
	while(r-l>1){
		int m=(l+r)/2;
		if(data[m-1]<t)
			l=m;
		else
			r=m;
	}
	return l;
}

void main(){
	int w,h,n;
	scanf("%d%d%d",&w,&h,&n);
	int[4][] lines = new int[4][n+4];
	int[] xs = new int[n+2];
	int vc=0;
	for(int i=0;i<n;i++){
		scanf("%d%d%d%d",&lines[i][0],&lines[i][1],&lines[i][2],&lines[i][3]);
		if(lines[i][0] == lines[i][2])
			xs[vc++] = lines[i][0];
	}
	lines[n] = [0,0,w,0];
	lines[n+1] = [0,h,w,h];
	lines[n+2] = [0,0,0,h];
	lines[n+3] = [w,0,w,h];
	n+=4;
	xs[vc++]=0;
	xs[vc++]=w;
	xs = xs[0..vc];
	sort(xs);
	
	alias Tuple!(int,"y",int,"type",int,"x",int,"v") query;
	query[] qs = new query[vc+n];
	int qc=0;
	for(int i=0;i<n;i++){
		if(lines[i][0] == lines[i][2]){
			int x = LowerBoundIdx(xs,lines[i][0]);
			qs[qc++] = query(lines[i][1],0,x,1);
			qs[qc++] = query(lines[i][3],2,x,-1);
		}else if(lines[i][1] == lines[i][3]){
			qs[qc++] = query(lines[i][1],1,LowerBoundIdx(xs,lines[i][0]),LowerBoundIdx(xs,lines[i][2]+1));
		}else
			assert(false);
	}
	sort(qs);
	
	int* numBuffer(int a){
		static int[] buffers = new int[1919810];
		static int nbc=0;
		buffers[nbc]=a;
		return &buffers[nbc++];
	}
	alias Tuple!(int,"x",int,"g",int*,"end") group;
	alias RedBlackTree!group gSet;
	gSet gs = new gSet;
	
	alias RedBlackTree!int iSet;
	iSet vs = new iSet;
	
	BinaryIndexedTree bit;
	bit.Initialize(vc);
	
	UnionFind uf;
	uf.Initialize(vc);
	int uc=0;
	
	long ans=0;
	
	for(int i=0;i<qc;i++){
		with(qs[i]){
			if(type==0){
				//add Vertical line
				assert(v==1);
				bit.Add(x,1);
				auto lb = gs.lowerBound(group(x,-1,null));
				if(!lb.empty){
					group pre = lb.back;
					assert(*pre.end!=x);
					if(*pre.end>x){
						group d;
						d.x = vs.upperBound(x).front;
						d.g = pre.g;
						d.end = numBuffer(*pre.end);
						gs.insert(d);
						*pre.end = vs.lowerBound(x).back;
					}
				}
				gs.insert(group(x,uc++,numBuffer(x)));
				vs.insert(x);
			}else if(type==1){
				//add Horizonal line
				int kind=0;
				auto lb = gs.lowerBound(group(x,-1,null));
				group ml;
				int mr;
				if(!lb.empty){
					group pre = lb.back;
					if(x<=*pre.end){
						kind=1;
						ml=pre;
						mr=*pre.end;
					}
				}
				auto ub = gs.upperBound(group(x,-1,null));
				while(!ub.empty){
					group nx = ub.front;
					ub.popFront;
					if(nx.x<v){
						if(kind==0){
							kind=1;
							ml=nx;
						}else{
							kind += uf.Unify(ml.g,nx.g);
							gs.removeKey(nx);
						}
						mr = *nx.end;
					}else
						break;
				}
				//writeln(qs[i]," ",kind);
				int bq = bit.Query(x,v);
				if(kind>0&&bq>0){
					*ml.end = mr;
					ans += bq-kind;
				}
			}else if(type==2){
				//remove Vertical line
				assert(v==-1);
				bit.Add(x,-1);
				auto lb = gs.lowerBound(group(x,1919114514,null));
				assert(!lb.empty);
				group pre = lb.back;
				if(pre.x == x){
					gs.removeKey(pre);
					if(*pre.end>x){
						pre.x=vs.upperBound(x).front;
						gs.insert(pre);
					}
				}else if(*pre.end==x){
					if(pre.x<x)
						*pre.end = vs.lowerBound(x).back;
					else
						assert(false);
				}else if(pre.x<x&&x<*pre.end){
					//do nothing
				}else
					assert(false);
				vs.removeKey(x);
			}else
				assert(false);
		}
	}
	
	printf("%lld\n",ans);
}