2018 ACM ICPC Asia Regional - Seoul A. Circuits
题意:
二维平面上有n个矩形,画两条平行于x周的直线,最多可以和多少个矩形相交。
n<=100000,坐标<=1e7
这两条直线一定可以和某两个矩形的上边界重合
枚举每一个矩形的上边界作为第一条直线
第二条直线可以借助线段树解决
具体方法是
先将所有矩形按上边界从小到大排序
枚举每个矩形,依次加入线段树
第一条线即为这个矩形的上边界
他的贡献是目前线段树里这个y坐标的矩形个数
所有矩形加入完毕后
从第一个矩形开始删除
线段树中剩余矩形个数最大的位置即为第二条线
即使多个上边界重合,也没有问题
相当于第一条直线累计这个矩形和排序在这个矩形之前的
第二条直线了累计排序在这个矩形之后的
#include<cstdio> #include<algorithm> using namespace std; #define N 100001 int mx[N<<3],tag[N<<3]; struct node { int yu,yd; }rec[N]; int has[N<<2],dyu[N],dyd[N]; int ori[N]; int tmp; bool cmp(node p,node q) { return p.yd<q.yd; } void down(int k) { mx[k<<1]+=tag[k]; mx[k<<1|1]+=tag[k]; tag[k<<1]+=tag[k]; tag[k<<1|1]+=tag[k]; tag[k]=0; } void insert(int k,int l,int r,int opl,int opr,int a) { if(l>=opl && r<=opr) { mx[k]+=a; tag[k]+=a; return; } if(tag[k]) down(k); int mid=l+r>>1; if(opl<=mid) insert(k<<1,l,mid,opl,opr,a); if(opr>mid) insert(k<<1|1,mid+1,r,opl,opr,a); mx[k]=max(mx[k<<1],mx[k<<1|1]); } void query(int k,int l,int r,int opl,int opr) { if(l>=opl && r<=opr) { tmp=max(tmp,mx[k]); return; } if(tag[k]) down(k); int mid=l+r>>1; if(opl<=mid) query(k<<1,l,mid,opl,opr); if(opr>mid) query(k<<1|1,mid+1,r,opl,opr); } int main() { int n,m=0; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%*d%d%*d%d",&rec[i].yu,&rec[i].yd); has[++m]=rec[i].yd; has[++m]=rec[i].yu; } sort(rec+1,rec+n+1,cmp); sort(has+1,has+m+1); m=unique(has+1,has+m+1)-has-1;; for(int i=1;i<=n;++i) { dyu[i]=lower_bound(has+1,has+m+1,rec[i].yu)-has; dyd[i]=lower_bound(has+1,has+m+1,rec[i].yd)-has; } for(int i=1;i<=n;++i) { insert(1,1,m,dyd[i],dyu[i],1); tmp=0; query(1,1,m,dyd[i],dyd[i]); ori[i]=tmp; } int ans=0; for(int i=1;i<=n;++i) { tmp=0; insert(1,1,m,dyd[i],dyu[i],-1); query(1,1,m,dyd[i]+1,m); // printf("%d\n",tmp); ans=max(ans,tmp+ori[i]); } printf("%d",ans); }