結果

問題 No.3709 Unknown Treasure
コンテスト
ユーザー あいすあうと
提出日時 2026-09-12 00:13:59
言語 C++23(gcc16)
(gcc 16.1.0 + boost 1.92.0 + ACL)
コンパイル:
g++-16 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
RE  
実行時間 -
コード長 23,513 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 9,311 ms
コンパイル使用メモリ 516,644 KB
実行使用メモリ 6,400 KB
最終ジャッジ日時 2026-09-12 00:14:17
合計ジャッジ時間 15,334 ms
ジャッジサーバーID
(参考情報)
judge1_0 / judge3_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 1 RE * 2
other AC * 2 WA * 1 RE * 33
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
using ll=long long;
using ull=unsigned long long;
using ld=long double;
using i128=__int128;
using P=pair<ll,ll>;
template<typename T> using vc=vector<T>;
template<typename T> using vv=vc<vc<T>>;
using vl=vc<ll>;
using vvl=vc<vc<ll>>;
using vul=vc<ull>;
using vs=vc<string>;
using vb=vc<bool>;
#define rep(i,s,n) for(ll i=s;i<(n);i++)
#define Rep(i,s,n) for(ll i=n;i>=s;i--)
#define nall(x) x.begin(),x.end()
#define rall(a) a.rbegin(),a.rend()
#define pb push_back
#define eb emplace_back
#define pob pop_back
#define nexp(v) next_permutation(v)
#define prep(v) prev_permutation(v)
#define YES cout<<"Yes"<<endl
#define NO cout<<"No"<<endl
#define YN {cout<<"Yes"<<endl;}else{cout<<"No"<<endl;}
#define M1 cout<<"-1"<<endl
const long long INF=(1LL<<62)-(1LL<<31)-1;
#define endl '\n'
using mint=modint998244353;
using mint7=modint1000000007;
//vl dx={1,-1,0,0};vl dy={0,0,1,-1};
//vl dx={0,0,1,1,1,-1,-1,-1};vl dy={1,-1,0,1,-1,0,1,-1};
bool out_grid(ll i, ll j, ll h, ll w){return (!(0<=i && i<h && 0<=j && j<w));}
void chmin(ll &a,ll b){if(a>b)a=b;}
void chmax(ll &a,ll b){if(a<b)a=b;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll ceil_div(ll a,ll b){return (a+(b-1))/b;}

template<typename T>
struct RangeSet{
	set<pair<T,T>> st;
	T TINF;

	RangeSet(){
		TINF=numeric_limits<T>::max()/2;
		st.emplace(TINF,TINF);
		st.emplace(-TINF,-TINF);
	}

	bool covered(T l,T r)const{
		assert(l<=r);
		auto ite=prev(st.lower_bound({l+1,l+1}));
		return ite->first<=l && r<=ite->second;
	}

	bool covered(T x)const{
		return covered(x,x);
	}

	pair<T,T> covered_by(T l,T r)const{
		assert(l<=r);
		auto ite=prev(st.lower_bound({l+1,l+1}));
		if(ite->first<=l && r<=ite->second)return *ite;
		return make_pair(-TINF,-TINF);
	}

	pair<T,T> covered_by(T x)const{
		return covered_by(x,x);
	}

	T insert(T l,T r){
		assert(l<=r);
		auto ite=prev(st.lower_bound({l+1,l+1}));
		if(ite->first<=l && r<=ite->second)return T(0);
		T sum_erased=T(0);
		if(ite->first<=l && l<=ite->second+1){
			l=ite->first;
			sum_erased+=ite->second-ite->first+1;
			ite=st.erase(ite);
		}else ite=next(ite);
		while(r>ite->second){
			sum_erased+=ite->second-ite->first+1;
			ite=st.erase(ite);
		}
		if(ite->first-1<=r && r<=ite->second){
			sum_erased+=ite->second-ite->first+1;
			r=ite->second;
			st.erase(ite);
		}
		st.emplace(l,r);
		return r-l+1-sum_erased;
	}

	T insert(T x){
		return insert(x,x);
	}

	T erase(T l,T r){
		assert(l<=r);
		auto ite=prev(st.lower_bound({l+1,l+1}));
		if(ite->first<=l && r<=ite->second){
			if(ite->first<l)st.emplace(ite->first,l-1);
			if(r<ite->second)st.emplace(r+1,ite->second);
			st.erase(ite);
			return r-l+1;
		}

		T ret=T(0);
		if(ite->first<=l && l<=ite->second){
			ret+=ite->second-l+1;
			if(ite->first<l)st.emplace(ite->first,l-1);
			ite=st.erase(ite);
		}else ite=next(ite);
		while(ite->second<=r){
			ret+=ite->second-ite->first+1;
			ite=st.erase(ite);
		}
		if(ite->first<=r && r<=ite->second){
			ret+=r-ite->first+1;
			if(r<ite->second)st.emplace(r+1,ite->second);
			st.erase(ite);
		}
		return ret;
	}

	T erase(T x){
		return erase(x,x);
	}

	int size()const{
		return (int)st.size()-2;
	}

	T mex(T x=0)const{
		auto ite=prev(st.lower_bound({x+1,x+1}));
		if(ite->first<=x && x<=ite->second)return ite->second+1;
		return x;
	}

	void output()const{
		cout<<"RangeSet : ";
		for(auto &p:st){
			if(p.first==-TINF || p.second==TINF)continue;
			cout<<"["<<p.first<<", "<<p.second<<"] ";
		}
		cout<<endl;
	}
};

template<typename T>
struct RangeSet2D{
	struct Node;
	using NP=shared_ptr<const Node>;
	using IV=vc<pair<T,T>>;
	struct Node{
		T l,r,sum;
		ull pri,h1,h2;
		int cnt;
		NP lc,rc;
		Node(T l,T r,ull pri,NP lc,NP rc,T sum,int cnt,ull h1,ull h2):l(l),r(r),sum(sum),pri(pri),h1(h1),h2(h2),cnt(cnt),lc(lc),rc(rc){}
	};
	struct HSeg{T x1,y,x2;};
	struct VSeg{T x,y1,y2;};
	struct Reflex{T x,y;int miss;};

	static ull mix(ull x){
		x+=0x9e3779b97f4a7c15ULL;
		x=(x^(x>>30))*0xbf58476d1ce4e5b9ULL;
		x=(x^(x>>27))*0x94d049bb133111ebULL;
		return x^(x>>31);
	}
	struct PairHash{
		size_t operator()(const pair<T,T> &p)const{
			ull a=(ull)hash<T>{}(p.first),b=(ull)hash<T>{}(p.second);
			return (size_t)mix(a^mix(b+0x9e3779b97f4a7c15ULL));
		}
	};

	map<T,NP> mp;
	T TINF;

	RangeSet2D(){
		TINF=numeric_limits<T>::max()/2;
		mp.emplace(-TINF,NP());
		mp.emplace(TINF,NP());
	}

	static T ysum(const NP &p){return p?p->sum:T(0);}
	static int ycnt(const NP &p){return p?p->cnt:0;}
	static ull yh1(const NP &p){return p?p->h1:0x243f6a8885a308d3ULL;}
	static ull yh2(const NP &p){return p?p->h2:0x13198a2e03707344ULL;}

	static ull priority(T x){
		return mix((ull)hash<T>{}(x)+0x9e3779b97f4a7c15ULL);
	}

	static bool higher(const NP &a,const NP &b){
		if(a->pri!=b->pri)return a->pri>b->pri;
		return a->l>b->l;
	}

	static NP make_node(T l,T r,const NP &lc=NP(),const NP &rc=NP()){
		ull p=priority(l);
		T s=ysum(lc)+(r-l+1)+ysum(rc);
		int c=ycnt(lc)+1+ycnt(rc);
		ull z1=mix((ull)hash<T>{}(l)^mix((ull)hash<T>{}(r)+0x243f6a8885a308d3ULL));
		ull z2=mix((ull)hash<T>{}(l)+0x13198a2e03707344ULL)^mix((ull)hash<T>{}(r));
		ull h1=mix(yh1(lc)^z1^mix(yh1(rc)+0xa4093822299f31d0ULL));
		ull h2=mix(yh2(lc)+z2+mix(yh2(rc)^0x082efa98ec4e6c89ULL));
		return make_shared<Node>(l,r,p,lc,rc,s,c,h1,h2);
	}

	static pair<NP,NP> ysplit(const NP &p,T key){
		if(!p)return {};
		if(p->l<key){
			auto [a,b]=ysplit(p->rc,key);
			return {make_node(p->l,p->r,p->lc,a),b};
		}else{
			auto [a,b]=ysplit(p->lc,key);
			return {a,make_node(p->l,p->r,b,p->rc)};
		}
	}

	static NP ymerge(const NP &a,const NP &b){
		if(!a)return b;
		if(!b)return a;
		if(higher(a,b))return make_node(a->l,a->r,a->lc,ymerge(a->rc,b));
		return make_node(b->l,b->r,ymerge(a,b->lc),b->rc);
	}

	static const Node* yprev(const NP &p,T x){
		const Node *ans=nullptr;
		auto cur=p;
		while(cur){
			if(cur->l<=x){ans=cur.get();cur=cur->rc;}
			else cur=cur->lc;
		}
		return ans;
	}

	static const Node* ylower(const NP &p,T x){
		const Node *ans=nullptr;
		auto cur=p;
		while(cur){
			if(cur->l>=x){ans=cur.get();cur=cur->lc;}
			else cur=cur->rc;
		}
		return ans;
	}

	static const Node* yfirst(const NP &p){
		if(!p)return nullptr;
		auto cur=p;
		while(cur->lc)cur=cur->lc;
		return cur.get();
	}

	static const Node* ylast(const NP &p){
		if(!p)return nullptr;
		auto cur=p;
		while(cur->rc)cur=cur->rc;
		return cur.get();
	}

	static bool yequal_exact(const NP &a,const NP &b){
		if(a.get()==b.get())return true;
		if(!a || !b)return false;
		if(a->l!=b->l || a->r!=b->r)return false;
		return yequal_exact(a->lc,b->lc) && yequal_exact(a->rc,b->rc);
	}

	static bool yequal(const NP &a,const NP &b){
		if(a.get()==b.get())return true;
		if(!a || !b)return false;
		if(a->cnt!=b->cnt || a->sum!=b->sum || a->h1!=b->h1 || a->h2!=b->h2)return false;
		return yequal_exact(a,b);
	}

	static bool ycovered(const NP &p,T l,T r){
		assert(l<=r);
		auto z=yprev(p,l);
		return z && z->l<=l && r<=z->r;
	}

	static T ymex(const NP &p,T x){
		auto z=yprev(p,x);
		if(z && z->l<=x && x<=z->r)return z->r+1;
		return x;
	}

	static pair<NP,T> yinsert(const NP &root,T l,T r){
		assert(l<=r);
		auto pre=yprev(root,l);
		if(pre && pre->l<=l && r<=pre->r)return {root,T(0)};
		T cut=l;
		if(pre && pre->r+1>=l)cut=pre->l;
		auto [a,b]=ysplit(root,cut);
		auto [m,c]=ysplit(b,r+2);
		T nl=l,nr=r;
		if(m){
			nl=min(nl,yfirst(m)->l);
			nr=max(nr,ylast(m)->r);
		}
		T d=nr-nl+1-ysum(m);
		auto z=make_node(nl,nr);
		return {ymerge(a,ymerge(z,c)),d};
	}

	static pair<NP,T> yerase(const NP &root,T l,T r){
		assert(l<=r);
		auto pre=yprev(root,l);
		bool hit=pre && pre->r>=l;
		if(!hit){
			auto nx=ylower(root,l);
			if(!nx || nx->l>r)return {root,T(0)};
		}
		T cut=hit?pre->l:l;
		auto [a,b]=ysplit(root,cut);
		auto [m,c]=ysplit(b,r+1);
		if(!m)return {root,T(0)};
		auto f=yfirst(m);
		auto z=ylast(m);
		NP mid;
		T keep=T(0);
		if(f->l<l){
			mid=ymerge(mid,make_node(f->l,l-1));
			keep+=l-f->l;
		}
		if(r<z->r){
			mid=ymerge(mid,make_node(r+1,z->r));
			keep+=z->r-r;
		}
		T d=ysum(m)-keep;
		return {ymerge(a,ymerge(mid,c)),d};
	}

	static void yintervals(const NP &root,IV &v){
		vc<NP> st;
		auto cur=root;
		while(cur || !st.empty()){
			while(cur){st.pb(cur);cur=cur->lc;}
			cur=st.back();st.pop_back();
			v.pb({cur->l,cur->r});
			cur=cur->rc;
		}
	}

	typename map<T,NP>::iterator split(T x){
		auto ite=mp.lower_bound(x);
		if(ite!=mp.end() && ite->first==x)return ite;
		assert(ite!=mp.begin());
		return mp.emplace_hint(ite,x,prev(ite)->second);
	}

	void merge(T l,T r){
		auto ite=mp.lower_bound(l);
		if(ite!=mp.begin())ite=prev(ite);
		while(ite!=mp.end()){
			auto nxt=next(ite);
			if(nxt==mp.end() || nxt->first>r)break;
			if(nxt->first!=TINF && yequal(ite->second,nxt->second))mp.erase(nxt);
			else ite=nxt;
		}
	}

	bool covered(T r1,T c1,T r2,T c2)const{
		assert(r1<=r2 && c1<=c2);
		assert(-TINF<r1 && r2<TINF && -TINF<c1 && c2<TINF);
		auto ite=prev(mp.upper_bound(r1));
		while(true){
			if(!ycovered(ite->second,c1,c2))return false;
			auto nxt=next(ite);
			if(nxt==mp.end() || nxt->first>r2)break;
			ite=nxt;
		}
		return true;
	}

	bool covered(T r,T c)const{return covered(r,c,r,c);}

	T insert(T r1,T c1,T r2,T c2){
		assert(r1<=r2 && c1<=c2);
		assert(-TINF<r1 && r2<TINF-1 && -TINF<c1 && c2<TINF-1);
		auto itr=split(r2+1);
		auto itl=split(r1);
		struct U{NP root;T d;};
		unordered_map<const Node*,U> memo;
		T ret=T(0);
		for(auto ite=itl;ite!=itr;++ite){
			const Node *key=ite->second.get();
			auto f=memo.find(key);
			if(f==memo.end()){
				auto [nr,d]=yinsert(ite->second,c1,c2);
				f=memo.emplace(key,U{nr,d}).first;
			}
			auto nxt=next(ite);
			ret+=(nxt->first-ite->first)*f->second.d;
			ite->second=f->second.root;
		}
		merge(r1,r2+1);
		return ret;
	}

	T insert(T r,T c){return insert(r,c,r,c);}

	T erase(T r1,T c1,T r2,T c2){
		assert(r1<=r2 && c1<=c2);
		assert(-TINF<r1 && r2<TINF-1 && -TINF<c1 && c2<TINF-1);
		auto itr=split(r2+1);
		auto itl=split(r1);
		struct U{NP root;T d;};
		unordered_map<const Node*,U> memo;
		T ret=T(0);
		for(auto ite=itl;ite!=itr;++ite){
			const Node *key=ite->second.get();
			auto f=memo.find(key);
			if(f==memo.end()){
				auto [nr,d]=yerase(ite->second,c1,c2);
				f=memo.emplace(key,U{nr,d}).first;
			}
			auto nxt=next(ite);
			ret+=(nxt->first-ite->first)*f->second.d;
			ite->second=f->second.root;
		}
		merge(r1,r2+1);
		return ret;
	}

	T erase(T r,T c){return erase(r,c,r,c);}

	T mex_y(T r,T c=0)const{
		assert(-TINF<r && r<TINF);
		auto ite=prev(mp.upper_bound(r));
		return ymex(ite->second,c);
	}

	T mex_x(T c,T r=0)const{
		assert(-TINF<r && r<TINF);
		auto ite=prev(mp.upper_bound(r));
		while(ycovered(ite->second,c,c)){
			auto nxt=next(ite);
			r=nxt->first;
			ite=nxt;
		}
		return r;
	}

	ll size()const{
		ll ret=0;
		for(auto ite=mp.begin();next(ite)!=mp.end();++ite)ret+=ycnt(ite->second);
		return ret;
	}

	static bool iv_covered(const IV &v,T l,T r){
		if(l>r)return true;
		int lo=0,hi=(int)v.size();
		while(lo<hi){
			int md=(lo+hi)/2;
			if(v[md].first<=l)lo=md+1;
			else hi=md;
		}
		if(lo==0)return false;
		auto [a,b]=v[lo-1];
		return a<=l && r<=b;
	}

	static shared_ptr<IV> intersect_iv(const shared_ptr<IV> &a,const shared_ptr<IV> &b,const shared_ptr<IV> &empty){
		if(a.get()==b.get())return a;
		if(a->empty() || b->empty())return empty;
		auto c=make_shared<IV>();
		int i=0,j=0;
		while(i<(int)a->size() && j<(int)b->size()){
			T l=max((*a)[i].first,(*b)[j].first);
			T r=min((*a)[i].second,(*b)[j].second);
			if(l<=r)c->pb({l,r});
			if((*a)[i].second<(*b)[j].second)i++;
			else j++;
		}
		if(c->empty())return empty;
		return c;
	}

	vc<array<T,4>> rectangles()const{
		vc<pair<T,NP>> nodes;
		for(auto ite=next(mp.begin());ite!=mp.end() && ite->first!=TINF;++ite)nodes.pb(*ite);
		if(nodes.size()<2)return {};

		unordered_map<const Node*,shared_ptr<IV>> cache;
		auto empty=make_shared<IV>();
		auto get_iv=[&](const NP &p)->shared_ptr<IV>{
			if(!p)return empty;
			auto f=cache.find(p.get());
			if(f!=cache.end())return f->second;
			auto v=make_shared<IV>();
			v->reserve(ycnt(p));
			yintervals(p,*v);
			cache[p.get()]=v;
			return v;
		};

		int nx=(int)nodes.size()-1;
		vc<T> xs(nodes.size());
		vc<shared_ptr<IV>> siv(nodes.size());
		rep(i,0,(ll)nodes.size()){
			xs[i]=nodes[i].first;
			siv[i]=get_iv(nodes[i].second);
		}

		vc<HSeg> hbound;
		vc<VSeg> vbound;
		vc<Reflex> rv;

		rep(i,0,nx){
			T x1=xs[i],x2=xs[i+1];
			for(auto [l,r]:*siv[i]){
				hbound.pb({x1,l,x2});
				hbound.pb({x1,r+1,x2});
			}
		}

		auto transition=[&](T x,const IV &a,const IV &b){
			vc<T> ea,eb;
			ea.reserve(a.size()*2);
			eb.reserve(b.size()*2);
			for(auto [l,r]:a){ea.pb(l);ea.pb(r+1);}
			for(auto [l,r]:b){eb.pb(l);eb.pb(r+1);}
			int i=0,j=0;
			bool sa=false,sb=false,has=false;
			T pre=T();
			while(i<(int)ea.size() || j<(int)eb.size()){
				T y;
				if(j==(int)eb.size() || (i<(int)ea.size() && ea[i]<eb[j]))y=ea[i];
				else if(i==(int)ea.size() || eb[j]<ea[i])y=eb[j];
				else y=ea[i];
				if(has && pre<y && sa!=sb)vbound.pb({x,pre,y});
				bool ba=sa,bb=sb;
				if(i<(int)ea.size() && ea[i]==y){sa=!sa;i++;}
				if(j<(int)eb.size() && eb[j]==y){sb=!sb;j++;}
				int q[4]={(int)ba,(int)bb,(int)sa,(int)sb};
				int cnt=q[0]+q[1]+q[2]+q[3];
				if(cnt==3){
					int miss=0;
					while(q[miss])miss++;
					rv.pb({x,y,miss});
				}
				pre=y;
				has=true;
			}
		};

		transition(xs[0],*empty,*siv[0]);
		rep(i,1,(ll)nodes.size())transition(xs[i],*siv[i-1],*siv[i]);

		int segN=1;
		while(segN<nx)segN<<=1;
		vc<shared_ptr<IV>> seg(segN*2,empty);
		rep(i,0,nx)seg[segN+i]=siv[i];
		for(int i=segN-1;i;i--)seg[i]=intersect_iv(seg[i<<1],seg[i<<1|1],empty);

		auto range_covered=[&](int l,int r,T a,T b)->bool{
			l+=segN;
			r+=segN;
			while(l<r){
				if(l&1){if(!iv_covered(*seg[l],a,b))return false;l++;}
				if(r&1){--r;if(!iv_covered(*seg[r],a,b))return false;}
				l>>=1;
				r>>=1;
			}
			return true;
		};

		int R=(int)rv.size();
		vc<int> ord(R);
		iota(nall(ord),0);
		vc<HSeg> hc;
		vc<VSeg> vcand;

		sort(nall(ord),[&](int a,int b){
			if(rv[a].y!=rv[b].y)return rv[a].y<rv[b].y;
			return rv[a].x<rv[b].x;
		});
		rep(k,1,R){
			auto &a=rv[ord[k-1]];
			auto &b=rv[ord[k]];
			if(a.y!=b.y || a.x==b.x)continue;
			int l=lower_bound(nall(xs),a.x)-xs.begin();
			int r=lower_bound(nall(xs),b.x)-xs.begin();
			if(range_covered(l,r,a.y-1,a.y))hc.pb({a.x,a.y,b.x});
		}

		sort(nall(ord),[&](int a,int b){
			if(rv[a].x!=rv[b].x)return rv[a].x<rv[b].x;
			return rv[a].y<rv[b].y;
		});
		rep(k,1,R){
			auto &a=rv[ord[k-1]];
			auto &b=rv[ord[k]];
			if(a.x!=b.x || a.y==b.y)continue;
			int z=lower_bound(nall(xs),a.x)-xs.begin();
			auto L=(z==0?empty:siv[z-1]);
			auto RR=siv[z];
			if(iv_covered(*L,a.y,b.y-1) && iv_covered(*RR,a.y,b.y-1))vcand.pb({a.x,a.y,b.y});
		}

		int H=(int)hc.size(),V=(int)vcand.size();
		vc<vc<int>> g(H);
		struct Ev{T x;int tp,id;};
		vc<Ev> ev;
		ev.reserve(H*2+V);
		rep(i,0,H){ev.pb({hc[i].x1,0,(int)i});ev.pb({hc[i].x2,2,(int)i});}
		rep(i,0,V)ev.pb({vcand[i].x,1,(int)i});
		sort(nall(ev),[](const Ev &a,const Ev &b){
			if(a.x!=b.x)return a.x<b.x;
			return a.tp<b.tp;
		});
		set<pair<T,int>> active;
		for(auto e:ev){
			if(e.tp==0)active.emplace(hc[e.id].y,e.id);
			else if(e.tp==2)active.erase({hc[e.id].y,e.id});
			else{
				auto &v=vcand[e.id];
				auto ite=active.lower_bound({v.y1,numeric_limits<int>::min()});
				while(ite!=active.end() && ite->first<=v.y2){
					g[ite->second].pb(e.id);
					++ite;
				}
			}
		}

		vc<int> ml(H,-1),mr(V,-1),dist(H);
		auto bfs=[&]()->bool{
			queue<int> q;
			fill(nall(dist),-1);
			rep(i,0,H)if(ml[i]==-1){dist[i]=0;q.push(i);}
			bool ok=false;
			while(!q.empty()){
				int u=q.front();q.pop();
				for(int v:g[u]){
					int w=mr[v];
					if(w==-1)ok=true;
					else if(dist[w]==-1){dist[w]=dist[u]+1;q.push(w);}
				}
			}
			return ok;
		};
		auto dfs=[&](auto &&self,int u)->bool{
			for(int v:g[u]){
				int w=mr[v];
				if(w==-1 || (dist[w]==dist[u]+1 && self(self,w))){
					ml[u]=v;
					mr[v]=u;
					return true;
				}
			}
			dist[u]=-1;
			return false;
		};
		while(bfs())rep(i,0,H)if(ml[i]==-1)dfs(dfs,i);

		vc<char> zh(H),zv(V);
		queue<pair<int,int>> q;
		rep(i,0,H)if(ml[i]==-1){zh[i]=1;q.emplace(0,i);}
		while(!q.empty()){
			auto [s,u]=q.front();q.pop();
			if(s==0){
				for(int v:g[u]){
					if(ml[u]==v || zv[v])continue;
					zv[v]=1;
					q.emplace(1,v);
				}
			}else if(mr[u]!=-1 && !zh[mr[u]]){
				zh[mr[u]]=1;
				q.emplace(0,mr[u]);
			}
		}

		vc<HSeg> selh;
		vc<VSeg> selv;
		unordered_set<pair<T,T>,PairHash> used;
		rep(i,0,H)if(zh[i]){
			selh.pb(hc[i]);
			used.emplace(hc[i].x1,hc[i].y);
			used.emplace(hc[i].x2,hc[i].y);
		}
		rep(i,0,V)if(!zv[i]){
			selv.pb(vcand[i]);
			used.emplace(vcand[i].x,vcand[i].y1);
			used.emplace(vcand[i].x,vcand[i].y2);
		}

		vc<int> rem;
		rep(i,0,R)if(!used.contains({rv[i].x,rv[i].y}))rem.pb(i);
		vc<HSeg> ext;
		vc<VSeg> barriers=vbound;
		for(auto z:selv)barriers.pb(z);

		if(!rem.empty()){
			vc<T> ys;
			ys.reserve(rem.size());
			for(int i:rem)ys.pb(rv[i].y);
			sort(nall(ys));
			ys.erase(unique(nall(ys)),ys.end());
			int sn=1;
			while(sn<(int)ys.size())sn<<=1;
			vc<T> mx(sn*2,-TINF),mn(sn*2,TINF);
			auto updmax=[&](int l,int r,T x){
				for(l+=sn,r+=sn;l<r;l>>=1,r>>=1){
					if(l&1)mx[l]=max(mx[l],x),l++;
					if(r&1)--r,mx[r]=max(mx[r],x);
				}
			};
			auto updmin=[&](int l,int r,T x){
				for(l+=sn,r+=sn;l<r;l>>=1,r>>=1){
					if(l&1)mn[l]=min(mn[l],x),l++;
					if(r&1)--r,mn[r]=min(mn[r],x);
				}
			};
			auto getmax=[&](int p){
				T ret=-TINF;
				for(p+=sn;p;p>>=1)ret=max(ret,mx[p]);
				return ret;
			};
			auto getmin=[&](int p){
				T ret=TINF;
				for(p+=sn;p;p>>=1)ret=min(ret,mn[p]);
				return ret;
			};
			vc<int> bo(barriers.size()),qo=rem;
			iota(nall(bo),0);
			sort(nall(bo),[&](int a,int b){return barriers[a].x<barriers[b].x;});
			sort(nall(qo),[&](int a,int b){return rv[a].x<rv[b].x;});
			vc<T> lans(R,-TINF),rans(R,TINF);
			int p=0;
			for(int id:qo){
				while(p<(int)bo.size() && barriers[bo[p]].x<rv[id].x){
					auto z=barriers[bo[p++]];
					int l=lower_bound(nall(ys),z.y1)-ys.begin();
					int r=upper_bound(nall(ys),z.y2)-ys.begin();
					if(l<r)updmax(l,r,z.x);
				}
				int y=lower_bound(nall(ys),rv[id].y)-ys.begin();
				lans[id]=getmax(y);
			}
			fill(nall(mn),TINF);
			sort(nall(bo),[&](int a,int b){return barriers[a].x>barriers[b].x;});
			sort(nall(qo),[&](int a,int b){return rv[a].x>rv[b].x;});
			p=0;
			for(int id:qo){
				while(p<(int)bo.size() && barriers[bo[p]].x>rv[id].x){
					auto z=barriers[bo[p++]];
					int l=lower_bound(nall(ys),z.y1)-ys.begin();
					int r=upper_bound(nall(ys),z.y2)-ys.begin();
					if(l<r)updmin(l,r,z.x);
				}
				int y=lower_bound(nall(ys),rv[id].y)-ys.begin();
				rans[id]=getmin(y);
			}
			for(int id:rem){
				auto z=rv[id];
				if(z.miss==0 || z.miss==2){
					assert(rans[id]!=TINF);
					ext.pb({z.x,z.y,rans[id]});
				}else{
					assert(lans[id]!=-TINF);
					ext.pb({lans[id],z.y,z.x});
				}
			}
		}

		vc<HSeg> hs=hbound;
		hs.insert(hs.end(),nall(selh));
		hs.insert(hs.end(),nall(ext));
		vc<VSeg> vs=vbound;
		vs.insert(vs.end(),nall(selv));

		auto merge_h=[&](vc<HSeg> a){
			sort(nall(a),[](const HSeg &p,const HSeg &q){
				if(p.y!=q.y)return p.y<q.y;
				if(p.x1!=q.x1)return p.x1<q.x1;
				return p.x2<q.x2;
			});
			vc<HSeg> b;
			for(auto z:a){
				if(z.x1==z.x2)continue;
				if(b.empty() || b.back().y!=z.y || b.back().x2<z.x1)b.pb(z);
				else b.back().x2=max(b.back().x2,z.x2);
			}
			return b;
		};
		auto merge_v=[&](vc<VSeg> a){
			sort(nall(a),[](const VSeg &p,const VSeg &q){
				if(p.x!=q.x)return p.x<q.x;
				if(p.y1!=q.y1)return p.y1<q.y1;
				return p.y2<q.y2;
			});
			vc<VSeg> b;
			for(auto z:a){
				if(z.y1==z.y2)continue;
				if(b.empty() || b.back().x!=z.x || b.back().y2<z.y1)b.pb(z);
				else b.back().y2=max(b.back().y2,z.y2);
			}
			return b;
		};
		hs=merge_h(move(hs));
		vs=merge_v(move(vs));

		vc<vc<T>> hp(hs.size()),vp(vs.size());
		rep(i,0,(ll)hs.size()){hp[i].pb(hs[i].x1);hp[i].pb(hs[i].x2);}
		rep(i,0,(ll)vs.size()){vp[i].pb(vs[i].y1);vp[i].pb(vs[i].y2);}
		vc<Ev> ev2;
		ev2.reserve(hs.size()*2+vs.size());
		rep(i,0,(ll)hs.size()){ev2.pb({hs[i].x1,0,(int)i});ev2.pb({hs[i].x2,2,(int)i});}
		rep(i,0,(ll)vs.size())ev2.pb({vs[i].x,1,(int)i});
		sort(nall(ev2),[](const Ev &a,const Ev &b){
			if(a.x!=b.x)return a.x<b.x;
			return a.tp<b.tp;
		});
		active.clear();
		for(auto e:ev2){
			if(e.tp==0)active.emplace(hs[e.id].y,e.id);
			else if(e.tp==2)active.erase({hs[e.id].y,e.id});
			else{
				auto z=vs[e.id];
				auto ite=active.lower_bound({z.y1,numeric_limits<int>::min()});
				while(ite!=active.end() && ite->first<=z.y2){
					hp[ite->second].pb(z.x);
					vp[e.id].pb(ite->first);
					++ite;
				}
			}
		}

		using Point=pair<T,T>;
		vc<pair<Point,Point>> edges;
		rep(i,0,(ll)hs.size()){
			auto &v=hp[i];
			sort(nall(v));
			v.erase(unique(nall(v)),v.end());
			rep(j,1,(ll)v.size())if(v[j-1]<v[j])edges.pb({{v[j-1],hs[i].y},{v[j],hs[i].y}});
		}
		rep(i,0,(ll)vs.size()){
			auto &v=vp[i];
			sort(nall(v));
			v.erase(unique(nall(v)),v.end());
			rep(j,1,(ll)v.size())if(v[j-1]<v[j])edges.pb({{vs[i].x,v[j-1]},{vs[i].x,v[j]}});
		}

		unordered_map<Point,int,PairHash> pid;
		vc<Point> pt;
		vc<array<int,4>> adj;
		auto gid=[&](Point p){
			auto f=pid.find(p);
			if(f!=pid.end())return f->second;
			int id=pt.size();
			pid[p]=id;
			pt.pb(p);
			adj.pb({-1,-1,-1,-1});
			return id;
		};
		auto dir=[&](Point a,Point b){
			if(b.first<a.first)return 0;
			if(b.second>a.second)return 1;
			if(b.first>a.first)return 2;
			return 3;
		};
		for(auto [a,b]:edges){
			int u=gid(a),v=gid(b);
			int d=dir(a,b);
			adj[u][d]=v;
			adj[v][(d+2)%4]=u;
		}

		vc<array<char,4>> seen(pt.size());
		vc<array<T,4>> ret;
		rep(s,0,(ll)pt.size())rep(sd,0,4){
			if(adj[s][sd]==-1 || seen[s][sd])continue;
			int u=s,d=sd;
			T lx=pt[u].first,rx=pt[u].first,ly=pt[u].second,ry=pt[u].second;
			int firstv=adj[u][d];
			T sr,sc;
			if(d==0){sr=pt[firstv].first;sc=pt[u].second;}
			else if(d==1){sr=pt[u].first;sc=pt[u].second;}
			else if(d==2){sr=pt[u].first;sc=pt[u].second-1;}
			else{sr=pt[u].first-1;sc=pt[firstv].second;}
			while(true){
				seen[u][d]=1;
				int v=adj[u][d];
				lx=min(lx,pt[v].first);rx=max(rx,pt[v].first);
				ly=min(ly,pt[v].second);ry=max(ry,pt[v].second);
				int nd=-1;
				int cand[4]={(d+1)%4,d,(d+3)%4,(d+2)%4};
				for(int z:cand)if(adj[v][z]!=-1){nd=z;break;}
				assert(nd!=-1);
				u=v;d=nd;
				if(u==s && d==sd)break;
			}
			bool inside=false;
			if(-TINF<sr && sr<TINF && -TINF<sc && sc<TINF)inside=covered(sr,sc);
			if(inside)ret.pb({lx,ly,rx-1,ry-1});
		}
		return ret;
	}

	void output()const{
		cout<<"RangeSet2D : ";
		for(auto ite=mp.begin();next(ite)!=mp.end();++ite){
			auto nxt=next(ite);
			if(ite->first==-TINF || nxt->first==TINF)continue;
			IV v;
			v.reserve(ycnt(ite->second));
			yintervals(ite->second,v);
			for(auto [l,r]:v)cout<<"["<<ite->first<<", "<<nxt->first-1<<"]x["<<l<<", "<<r<<"] ";
		}
		cout<<endl;
	}
};

int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	ll h,w,n;
	cin >> h >> w >> n;
	RangeSet2D<ll> st;
	rep(i,0,n){
		ll r1,c1,r2,c2;
		cin >> r1 >> c1 >> r2 >> c2;
		st.insert(r1,r2,c1,c2);
	}
	auto rect=st.rectangles();
	//st.output();
	ll sum=0;
	for(auto [r1,c1,r2,c2]:rect)sum+=(r2-r1+1)*(c2-c1+1);
	cout << h*w-sum << endl;
}
0