bzoj 4237 稻草人

匿名 (未验证) 提交于 2019-12-03 00:02:01

bzoj

这个矩形有三个限制,分别是右上角点的横纵坐标分别大于左下角废话,并且中间区域没有点.那么可以先按横坐标排序,然后枚举左边的点和右边的点匹配.为了保证复杂度,这里每次把点集一分为二,先递归处理两边,然后处理两端点分别在左右两边的情况

这里把两边的点分别按纵坐标排序,然后枚举右边的点,每次把左边纵坐标小于右端点的点加进来.然后考虑中间区域没有点的限制,如果左边某个点在某个时刻右上方有点,那么这个点就不能作为端点.左侧可以维护一个从左往右纵坐标单调递减的单调栈.然后考虑右侧其他点对当前右端点的影响,如果有个点在右端点左下方,那么比那个点纵坐标小的左边的点就不能作为左端点.所以如果右边维护一个从左往右纵坐标单调递增的单调栈,那么就可以二分出那个左下的点,推出左端点的纵坐标最小是多少.再在左边单调栈二分出纵坐标最小的满足条件的左端点的位置,那么这个位置到栈顶之间的点都可以作为左端点

#include<bits/stdc++.h> #define LL long long #define uLL unsigned long long #define db double  using namespace std; const int N=2e5+10; int rd() {     int x=0,w=1;char ch=0;     while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}     return x*w; } struct node {     int x,y; }a[N]; bool cmp1(node aa,node bb){return aa.x<bb.x;} bool cmp2(node aa,node bb){return aa.y<bb.y;} int n,st[N]; LL ans; void cdq(int l,int r) {     if(l==r) return;     int mid=(l+r)>>1;     cdq(l,mid),cdq(mid+1,r);     int tl=l-1,tr=mid;     sort(a+l,a+mid+1,cmp2);     sort(a+mid+1,a+r+1,cmp2);     for(int i=mid+1,j=l;i<=r;++i)     {         while(j<=mid&&a[j].y<a[i].y)         {             while(tl>=l&&a[st[tl]].x<a[j].x) --tl;             st[++tl]=j;             ++j;         }         int ll=mid+1,rr=tr,z=0;         while(ll<=rr)         {             int md=(ll+rr)>>1;             if(a[st[md]].x<a[i].x) z=st[md],ll=md+1;             else rr=md-1;         }         int ql=l-1;         ll=l,rr=tl;         while(ll<=rr)         {             int md=(ll+rr)>>1;             if(a[st[md]].y<a[z].y) ql=md,ll=md+1;             else rr=md-1;         }         ans+=max(tl-ql,0);         while(tr>mid&&a[st[tr]].x>a[i].x) --tr;         st[++tr]=i;     } }  int main() {     n=rd();     for(int i=1;i<=n;++i) a[i].x=rd(),a[i].y=rd();     sort(a+1,a+n+1,cmp1);     cdq(1,n);     printf("%lld\n",ans);     return 0;  }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!