CF983D Arkady and Rectangles

CF983D Arkady and Rectangles

题意:按顺序画\(n\)个颜色不同的矩形(后画的覆盖先画的),问最后能看见多少种颜色

\(n\leq 100000.x,y\in [-10^9,10^9]\)

由数据规模可得正解应该为\(n\log^2n(n\sqrt n?)\)

对于矩形覆盖类问题,不难想到扫描线,关键是如何扫?

我们考虑对于每个节点,维护一个\(set\)存储完全覆盖当前节点的颜色以及能在当前节点看见的未被看见过的最大和最小颜色

所以我们扫描\(x\)轴,离散化\(y\)轴,并建立线段树套\(set\),每次得到新颜色时就在线段树中删去颜色对应区间。

当然,如果觉得\(set\)常数太大,也可以用\(2\)个优先队列代替,一个维护加入,一个维护弹出。

细节详见代码:

\(\mathfrak{Talk\ is\ cheap,show\ you\ the\ code.}\)

#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define read read1<ll>()
# define Type template<typename T>
Type T read1(){
	T t=0;char k;bool vis=0;
	do (k=getchar())=='-'&&(vis=1);while('0'>k||k>'9');
	while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
	return vis?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
struct A{
	int l,r,w,c;
	A(int _l=0,int _r=0,int _w=0,int _c=0):l(_l),r(_r),w(_w),c(_c){}
	bool operator <(const A &b)const{return w<b.w;}
}a[200005];
pair<int,int>fr[100005];
int s,f[200005];bool vis[100005],use[100005];
priority_queue<int>q[800005],q_[800008];
int mx[800005],mn[800005];
void pushup(int d,bool x){
	x?mx[d]=mn[d]=0:mx[d]=max(mx[d<<1],mx[d<<1|1]),mn[d]=min(mn[d<<1],mn[d<<1|1]);
	if(q[d].size())use[q[d].top()]?mn[d]=max(mn[d],q[d].top()):mx[d]=max(mx[d],q[d].top());
	if(mx[d]<mn[d])mx[d]=0;
}
void add(int l,int r,int tl,int tr,int w,int d){
	if(l==tl&&r==tr){
		if(w)if(vis[w])q_[d].push(w);
			else q[d].push(w);
		while(q_[d].size()&&q[d].top()==q_[d].top())q[d].pop(),q_[d].pop();
		pushup(d,tl==tr);
		return;
	}
	int mid=tl+tr>>1;
	if(r<=mid)add(l,r,tl,mid,w,d<<1);
	else if(mid<l)add(l,r,mid+1,tr,w,d<<1|1);
	else add(l,mid,tl,mid,w,d<<1),add(mid+1,r,mid+1,tr,w,d<<1|1);
	pushup(d,0);
}
# define In(x) (lower_bound(f+1,f+f[0]+1,x)-f)
int main(){
	s=read;int n=s<<1;
	for(int i=0;i<s;++i){
		int lx=read,ly=read,rx=read,ry=read;
		a[i<<1]=A(ly,ry,lx,i+1);
		a[i<<1|1]=A(ly,ry,rx,i+1);
		f[++f[0]]=ly;f[++f[0]]=ry;
		fr[i+1]=make_pair(ly,ry);
	}
	sort(f+1,f+f[0]+1);
	f[0]=unique(f+1,f+f[0]+1)-f-1;
	sort(a,a+n);
	for(int i=1;i<=s;++i)
		fr[i]=make_pair(In(fr[i].first),In(fr[i].second));
	int ans=1;
	for(int i=0;i<n;){
		do add(a[i].l=In(a[i].l),a[i].r=In(a[i].r)-1,1,f[0],a[i].c,1),vis[a[i].c]=1;while(++i<n&&a[i].w==a[i-1].w);
		while(mx[1]){
			use[mx[1]]=1;++ans;
			add(fr[mx[1]].first,fr[mx[1]].second-1,1,f[0],0,1);
		}
	}
	cout<<ans;
	return 0;
}

注意题目中的矩形描述不是格子位置而是格点位置!

posted @ 2021-02-25 22:00  ファイナル  阅读(95)  评论(0)    收藏  举报