这个题要求解最后的颜色数
显然二维线段树可以选择,但是空间过大
那我们应该如何进行维护呢
考虑扫描线
对于非扫描的一维维护线段树
由于颜色很多,在扫描线上又要支持删除,所以考虑对颜色的集合进行维护
每个节点保存这个区间是否被完全覆盖、可以用来更新答案的最大颜色是哪个、最小的裸露在外的颜色是哪个
可以用平衡树维护这个集合从而进行节点信息的更新
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef double db;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=10*x+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=200100;
int n;
int L[N],R[N],U[N],D[N];
namespace hsh_map
{
int tot,X[N],Y[N];
int binary_search(int *a,int x)
{
int l(1),r(tot),mid;
while(l<=r)
{
mid=(l+r)>>1;
a[mid]<=x ? l=mid+1 : r=mid-1;
}
return l-1;
}
void Main()
{
register int i;
for(i=1;i<=n;++i)
X[++tot]=L[i],Y[tot]=D[i],
X[++tot]=R[i],Y[tot]=U[i];
sort(X+1,X+1+tot),sort(Y+1,Y+1+tot);
for(i=1;i<=n;++i)
L[i]=binary_search(X,L[i]),R[i]=binary_search(X,R[i]),
D[i]=binary_search(Y,D[i]),U[i]=binary_search(Y,U[i]);
}
}
struct node
{
set<int> st[2];
int top[2],cover,mx_remain,mn_cover;
node(){top[0]=top[1]=cover=mx_remain=mn_cover=-1;}
void erase(int x)
{st[0].erase(x),st[1].erase(x);}
void insert(int x)
{st[0].insert(x);}
void move(int x)
{st[0].erase(x),st[1].insert(x);}
void update()
{
top[0]=st[0].size() ? *st[0].rbegin() : -1;
top[1]=st[1].size() ? *st[1].rbegin() : -1;
cover=max(top[0],top[1]);
}
}v[N<<2];
// vertex
inline void pushup(int k,int l,int r)
{
if(l==r)
{
v[k].mn_cover=v[k].cover,
v[k].mx_remain=v[k].top[0]>v[k].top[1] ? v[k].top[0] : -1;
return ;
}
int ls=k<<1,rs=k<<1|1;
v[k].mn_cover=max(v[k].cover,min(v[ls].mn_cover,v[rs].mn_cover));
v[k].mx_remain=max(v[k].top[0],max(v[ls].mx_remain,v[rs].mx_remain));
if(v[k].mx_remain<v[k].mn_cover) v[k].mx_remain=-1;
}
void insert(int k,int l,int r,int x,int y,int val)
{
if(x<=l && y>=r)
{
v[k].insert(val);
v[k].update();
pushup(k,l,r);
return ;
}
int mid=(l+r)>>1;
if(x<=mid) insert(k<<1,l,mid,x,y,val);
if(y>mid) insert(k<<1|1,mid+1,r,x,y,val);
pushup(k,l,r);
}
void del(int k,int l,int r,int x,int y,int val)
{
if(x<=l && y>=r)
{
v[k].erase(val);
v[k].update();
pushup(k,l,r);
return ;
}
int mid=(l+r)>>1;
if(x<=mid) del(k<<1,l,mid,x,y,val);
if(y>mid) del(k<<1|1,mid+1,r,x,y,val);
pushup(k,l,r);
}
void move(int k,int l,int r,int x,int y,int val)
{
if(x<=l && y>=r)
{
v[k].move(val);
v[k].update();
pushup(k,l,r);
return ;
}
int mid=(l+r)>>1;
if(x<=mid) move(k<<1,l,mid,x,y,val);
if(y>mid) move(k<<1|1,mid+1,r,x,y,val);
pushup(k,l,r);
}
struct rectangle{int d,u,opt,pos;};
vector<rectangle> rec[N];
int main()
{
n=read();
register int i,j;
for(i=1;i<=n;++i)
L[i]=read(),D[i]=read(),
R[i]=read(),U[i]=read();
hsh_map::Main();
for(i=1;i<=n;++i)
U[i]--,
rec[L[i]].push_back((rectangle){D[i],U[i],1,i}),
rec[R[i]].push_back((rectangle){D[i],U[i],0,i});
int ans(1);
for(i=1;i<=n+n;++i)
{
for(j=0;j<rec[i].size();++j)
rec[i][j].opt ? insert(1,1,n+n,rec[i][j].d,rec[i][j].u,rec[i][j].pos) : del(1,1,n+n,rec[i][j].d,rec[i][j].u,rec[i][j].pos);
while(v[1].mx_remain!=-1)
ans++,move(1,1,n+n,D[v[1].mx_remain],U[v[1].mx_remain],v[1].mx_remain);
}
cout<<ans<<endl;
return 0;
}