CF 983D Arkady and Rectangles

xiaoxiao2021-03-01  6

Arkady and Rectangles

题目描述 传送门:http://codeforces.com/contest/983/problem/D

题解 倒过来然后裸上树套树的话似乎会mle。 考虑离线,颜色的编号等于时间戳。 然后对于x轴扫描线,用线段树维护y坐标的情况。 对于一个矩形,如果它在x坐标扫到某个位置并且操作完的时候,某一段能够显示出来,那么这个矩形就可见。 所以我们按照x坐标扫描线,每次先把矩形删除加上,然后取出所有可视矩形计算答案。

接下来我们考虑下线段树要怎么维护。 对于线段树上的每个点维护一个set表示覆盖这个区间的所有矩形的颜色序号。 线段树上每个节点再维护两个值maxn,minn,分别表示该区间可视的颜色虽大编号和最小编号。 对于转移,一个区间上如果最大的那个颜色已经被记录答案那么maxn=0,否则maxn为子树和set里的最大值。 最小直接转移就好了。 每一个x坐标处理完之后我们取线段树根节点的manx并记录答案并进行修改,然后依次这么做下去直到maxn[root]=0。

这样的话时间复杂度是O(nlog2n)。

代码

#include<bits/stdc++.h> #define N 200005 using namespace std; int n,A[N],B[N],C[N],D[N],ans,flag[N]; int n1[N],n2[N],t1,t2,T1,T2; struct info{int maxn,minn;}t[N*4]; vector<int>s[N]; set<int>q[N*4]; class seg_tree { void update(int x,int l,int r) { int lc=x<<1,rc=lc+1; if(l==r)t[x].minn=t[x].maxn=0; else { t[x].minn=min(t[lc].minn,t[rc].minn); t[x].maxn=max(t[lc].maxn,t[rc].maxn); } if(q[x].size()) { if(flag[*q[x].rbegin()]) t[x].minn=max(t[x].minn,*q[x].rbegin()); else t[x].maxn=max(t[x].maxn,*q[x].rbegin()); } if(t[x].maxn<t[x].minn)t[x].maxn=0; } public: void modify(int x,int l,int r,int ql,int qr,int col) { if(ql<=l&&r<=qr) { if(col>0)q[x].insert(col); else q[x].erase(-col); update(x,l,r);return; } int mid=l+r>>1,lc=x<<1,rc=lc+1; if(ql<=mid)modify(lc,l,mid,ql,qr,col); if(qr>mid)modify(rc,mid+1,r,ql,qr,col); update(x,l,r); } }T; int main() { int x,y; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d%d%d",&A[i],&B[i],&C[i],&D[i]); n1[++t1]=A[i];n1[++t1]=C[i]; n2[++t2]=B[i];n2[++t2]=D[i]; } sort(n1+1,n1+t1+1);sort(n2+1,n2+t2+1); T1=unique(n1+1,n1+t1+1)-n1-1; T2=unique(n2+1,n2+t2+1)-n2-1; for(int i=1;i<=n;i++) { A[i]=lower_bound(n1+1,n1+T1+1,A[i])-n1; B[i]=lower_bound(n2+1,n2+T2+1,B[i])-n2; C[i]=lower_bound(n1+1,n1+T1+1,C[i])-n1; D[i]=lower_bound(n2+1,n2+T2+1,D[i])-n2-1; s[A[i]].push_back(i); s[C[i]].push_back(-i); } for(int i=1;i<=T1;i++) { for(int j=0;j<s[i].size();j++) { y=s[i][j];x=abs(y); T.modify(1,1,T2,B[x],D[x],y); } while(t[1].maxn) { x=t[1].maxn;flag[x]=1;ans++; T.modify(1,1,T2,B[x],D[x],0); } } printf("%d\n",ans+1); return 0; }
转载请注明原文地址: https://www.6miu.com/read-3650292.html

最新回复(0)