結果

問題 No.3709 Unknown Treasure
コンテスト
ユーザー あいすあうと
提出日時 2026-09-11 22:29:40
言語 C++23
(gcc 15.3.0 + boost 1.92.0 + ACL)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 76 ms / 2,000 ms
+ 542µs
コード長 11,383 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 5,579 ms
コンパイル使用メモリ 415,172 KB
実行使用メモリ 6,400 KB
最終ジャッジ日時 2026-09-11 22:30:09
合計ジャッジ時間 9,357 ms
ジャッジサーバーID
(参考情報)
judge2_0 / judge1_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 36
権限があれば一括ダウンロードができます

ソースコード

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{
	map<T,RangeSet<T>> mp;
	T TINF;

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

	typename map<T,RangeSet<T>>::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 && ite->second.st==nxt->second.st)mp.erase(nxt);
			else ite=nxt;
		}
	}

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

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

	T insert(T xl,T xr,T yl,T yr){
		assert(xl<=xr && yl<=yr);
		assert(-TINF<xl && xr<TINF-1);
		auto itr=split(xr+1);
		auto itl=split(xl);
		T ret=T(0);
		for(auto ite=itl;ite!=itr;++ite){
			auto nxt=next(ite);
			ret+=(nxt->first-ite->first)*ite->second.insert(yl,yr);
		}
		merge(xl,xr+1);
		return ret;
	}

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

	T erase(T xl,T xr,T yl,T yr){
		assert(xl<=xr && yl<=yr);
		assert(-TINF<xl && xr<TINF-1);
		auto itr=split(xr+1);
		auto itl=split(xl);
		T ret=T(0);
		for(auto ite=itl;ite!=itr;++ite){
			auto nxt=next(ite);
			ret+=(nxt->first-ite->first)*ite->second.erase(yl,yr);
		}
		merge(xl,xr+1);
		return ret;
	}

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

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

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

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

	vc<array<T,4>> rectangles()const{
		vc<T> xs,ys;
		for(auto ite=mp.begin();next(ite)!=mp.end();++ite){
			auto nxt=next(ite);
			if(ite->first==-TINF || nxt->first==TINF)continue;
			bool ok=false;
			for(auto &p:ite->second.st){
				if(p.first==-ite->second.TINF || p.second==ite->second.TINF)continue;
				ok=true;
				ys.pb(p.first);
				ys.pb(p.second+1);
			}
			if(!ok)continue;
			xs.pb(ite->first);
			xs.pb(nxt->first);
		}
		if(xs.empty())return {};
		sort(nall(xs));
		xs.erase(unique(nall(xs)),xs.end());
		sort(nall(ys));
		ys.erase(unique(nall(ys)),ys.end());

		int nx=(int)xs.size()-1;
		int ny=(int)ys.size()-1;
		vc<vc<char>> a(nx,vc<char>(ny));

		rep(i,0,nx){
			auto ite=prev(mp.upper_bound(xs[i]));
			rep(j,0,ny){
				a[i][j]=ite->second.covered(ys[j]);
			}
		}

		struct R{
			int x,y,miss;
		};

		vc<R> rv;
		vc<vc<int>> id(nx+1,vc<int>(ny+1,-1));

		auto cell=[&](int x,int y)->int{
			if(x<0 || nx<=x || y<0 || ny<=y)return 0;
			return a[x][y];
		};

		rep(i,0,nx+1)rep(j,0,ny+1){
			array<int,4> q={
				cell(i-1,j-1),
				cell(i,j-1),
				cell(i-1,j),
				cell(i,j)
			};
			int cnt=q[0]+q[1]+q[2]+q[3];
			if(cnt!=3)continue;
			int miss=0;
			while(q[miss])miss++;
			id[i][j]=(int)rv.size();
			rv.pb({(int)i,(int)j,miss});
		}

		set<array<int,4>> hs,vs;

		for(auto [x,y,miss]:rv){
			if(miss==0 || miss==2){
				int k=x;
				while(k<nx && 0<y && y<ny && a[k][y-1] && a[k][y])k++;
				if(id[k][y]!=-1)hs.insert({x,y,k,y});
			}else{
				int k=x;
				while(0<k && 0<y && y<ny && a[k-1][y-1] && a[k-1][y])k--;
				if(id[k][y]!=-1)hs.insert({k,y,x,y});
			}

			if(miss==0 || miss==1){
				int k=y;
				while(k<ny && 0<x && x<nx && a[x-1][k] && a[x][k])k++;
				if(id[x][k]!=-1)vs.insert({x,y,x,k});
			}else{
				int k=y;
				while(0<k && 0<x && x<nx && a[x-1][k-1] && a[x][k-1])k--;
				if(id[x][k]!=-1)vs.insert({x,k,x,y});
			}
		}

		vc<array<int,4>> h(nall(hs));
		vc<array<int,4>> v(nall(vs));

		int H=(int)h.size();
		int V=(int)v.size();

		vc<vc<int>> g(H);

		rep(i,0,H)rep(j,0,V){
			if(h[i][0]<=v[j][0] && v[j][0]<=h[i][2] &&
			   v[j][1]<=h[i][1] && h[i][1]<=v[j][3]){
				g[i].pb(j);
			}
		}

		vc<int> mt(V,-1);
		vc<int> ml(H,-1);

		function<bool(int,vc<char>&)> dfs=[&](int x,vc<char> &seen)->bool{
			for(auto y:g[x]){
				if(seen[y])continue;
				seen[y]=1;
				if(mt[y]==-1 || dfs(mt[y],seen)){
					mt[y]=x;
					ml[x]=y;
					return true;
				}
			}
			return false;
		};

		rep(i,0,H){
			vc<char> seen(V);
			dfs(i,seen);
		}

		vc<char> zh(H);
		vc<char> zv(V);
		queue<pair<int,int>> q;

		rep(i,0,H){
			if(ml[i]!=-1)continue;
			zh[i]=1;
			q.emplace(0,i);
		}

		while(!q.empty()){
			auto [side,u]=q.front();
			q.pop();

			if(side==0){
				for(auto y:g[u]){
					if(ml[u]==y || zv[y])continue;
					zv[y]=1;
					q.emplace(1,y);
				}
			}else{
				if(mt[u]!=-1 && !zh[mt[u]]){
					zh[mt[u]]=1;
					q.emplace(0,mt[u]);
				}
			}
		}

		vc<vc<char>> hb(nx,vc<char>(ny+1));
		vc<vc<char>> vb(nx+1,vc<char>(ny));
		vc<vc<char>> used(nx+1,vc<char>(ny+1));

		rep(i,0,H){
			if(!zh[i])continue;
			auto [x1,y1,x2,y2]=h[i];
			rep(x,x1,x2)hb[x][y1]=1;
			used[x1][y1]=1;
			used[x2][y2]=1;
		}

		rep(i,0,V){
			if(zv[i])continue;
			auto [x1,y1,x2,y2]=v[i];
			rep(y,y1,y2)vb[x1][y]=1;
			used[x1][y1]=1;
			used[x2][y2]=1;
		}

		auto has_v=[&](int x,int y)->bool{
			return (y<ny && vb[x][y]) || (0<y && vb[x][y-1]);
		};

		for(auto [x,y,miss]:rv){
			if(used[x][y])continue;

			if(miss==0 || miss==2){
				int cur=x;
				while(cur<nx){
					if(has_v(cur,y))break;
					if(!(0<y && y<ny && a[cur][y-1] && a[cur][y]))break;
					hb[cur][y]=1;
					cur++;
				}
			}else{
				int cur=x;
				while(0<cur){
					if(has_v(cur,y))break;
					int k=cur-1;
					if(!(0<y && y<ny && a[k][y-1] && a[k][y]))break;
					hb[k][y]=1;
					cur--;
				}
			}
		}

		vc<vc<char>> seen(nx,vc<char>(ny));
		vc<array<T,4>> ret;

		rep(si,0,nx)rep(sj,0,ny){
			if(!a[si][sj] || seen[si][sj])continue;

			queue<pair<int,int>> que;
			que.emplace(si,sj);
			seen[si][sj]=1;

			int lx=si;
			int rx=si;
			int ly=sj;
			int ry=sj;
			ll cnt=0;

			while(!que.empty()){
				auto [x,y]=que.front();
				que.pop();

				cnt++;
				lx=min(lx,x);
				rx=max(rx,x);
				ly=min(ly,y);
				ry=max(ry,y);

				if(0<x && a[x-1][y] && !vb[x][y] && !seen[x-1][y]){
					seen[x-1][y]=1;
					que.emplace(x-1,y);
				}

				if(x+1<nx && a[x+1][y] && !vb[x+1][y] && !seen[x+1][y]){
					seen[x+1][y]=1;
					que.emplace(x+1,y);
				}

				if(0<y && a[x][y-1] && !hb[x][y] && !seen[x][y-1]){
					seen[x][y-1]=1;
					que.emplace(x,y-1);
				}

				if(y+1<ny && a[x][y+1] && !hb[x][y+1] && !seen[x][y+1]){
					seen[x][y+1]=1;
					que.emplace(x,y+1);
				}
			}

			assert(cnt==(ll)(rx-lx+1)*(ry-ly+1));

			ret.pb({
				xs[lx],
				ys[ly],
				xs[rx+1]-1,
				ys[ry+1]-1
			});
		}

		return ret;
	}

	void output()const{
		cout<<"RangeSet2D : ";
		for(auto ite=mp.begin();next(ite)!=mp.end();++ite){
			auto nxt=next(ite);
			for(auto &p:ite->second.st){
				if(p.first==-ite->second.TINF || p.second==ite->second.TINF)continue;
				if(ite->first==-TINF || nxt->first==TINF)continue;
				cout<<"["<<ite->first<<", "<<nxt->first-1<<"]x["<<p.first<<", "<<p.second<<"] ";
			}
		}
		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