BZOJ3356 : [Usaco2004 Jan]禁闭围栏
首先将坐标离散化,考虑从左往右扫描线
碰到插入操作则插入
碰到删除操作的:
当前包含i的矩形数=y1在[1,y2[i]]之间的矩形数-y2在[1,y1[i]-1]之间的矩形数
用两棵树状数组维护即可,时间复杂度O(n\log n)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include<cstdio> #include<algorithm> #define N 500010 int n,m,i,x1,y1,x2,y2,b[N],bl[N],br[N],now,ans=-1,cnt; struct P{ int x,l,r,t;}a[N]; inline bool cmp(P a,P b){ return a.x<b.x;} inline void addl( int x, int y){ for (;x<=m;x+=x&-x)bl[x]+=y;} inline void addr( int x, int y){ for (;x<=m;x+=x&-x)br[x]+=y;} inline int askl( int x){ int t=0; for (;x;x-=x&-x)t+=bl[x]; return t;} inline int askr( int x){ int t=0; for (;x;x-=x&-x)t+=br[x]; return t;} inline int lower( int x){ int l=1,r=m,mid,t; while (l<=r) if (b[mid=(l+r)>>1]<=x)l=(t=mid)+1; else r=mid-1; return t; } inline void read( int &a){ char c; while (!(((c= getchar ())>= '0' )&&(c<= '9' )));a=c- '0' ; while (((c= getchar ())>= '0' )&&(c<= '9' ))(a*=10)+=c- '0' ;} int main(){ read(n); while (n--){ read(x1),read(y1),read(x2),read(y2); a[++m].x=x1,a[m].l=b[m]=y1,a[m].r=y2,a[m].t=1; a[++m].x=x2,a[m].l=y1,a[m].r=b[m]=y2; } for (std::sort(b+1,b+m+1),std::sort(a+1,a+m+1,cmp),i=1;i<=m;i++){ a[i].l=lower(a[i].l),a[i].r=lower(a[i].r); if (a[i].t)addl(a[i].l,1),addr(a[i].r,1); else { now=askl(a[i].r)-askr(a[i].l-1); if (now>ans)ans=now,cnt=1; else if (now==ans)cnt++; addl(a[i].l,-1),addr(a[i].r,-1); } } return printf ( "%d %d" ,ans,cnt),0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步