题目大意:
网格上有些点
找出一些点对使这两个点围成的矩形内没有点
思路:
我们先用cdq降低复杂度
然后对于分治的两边
左右两端分别按照y排序
然后我们对于右边的点 只需要统计出以它为右上角顶点的矩形即可
我们直接通过对于左右两边分别维护两个单调栈
左边x单减 右边x单增
然后每次在右边插入点的时候把左边y小于它的加入栈
直接在左边的栈里二分查找答案
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 200100 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 struct data {int x,y;}g[MAXN],s1[MAXN],s2[MAXN]; 21 int n,t1,t2,pos; 22 bool cmp(data a,data b) {return (a.x==b.x&&a.y<b.y)||a.x<b.x;} 23 bool Cmp(data a,data b) {return (a.y==b.y&&a.x<b.x)||a.y<b.y;} 24 ll ans=0; 25 void cdq(int l,int r) 26 { 27 if(l==r) return; 28 int mid=l+r>>1; 29 cdq(l,mid);cdq(mid+1,r); 30 sort(g+l,g+mid+1,Cmp);sort(g+mid+1,g+r+1,Cmp); 31 t1=t2=0,pos=l; 32 for(int i=mid+1;i<=r;i++) 33 { 34 while(t1&&s1[t1].x>=g[i].x) t1--; 35 s1[++t1]=g[i]; 36 while(pos<=mid&&g[pos].y<g[i].y) 37 { 38 while(t2&&s2[t2].x<=g[pos].x) t2--; 39 s2[++t2]=g[pos++]; 40 } 41 ans+=(ll)(t2-(lower_bound(s2+1,s2+t2+1,s1[t1-1],Cmp)-s2)+1); 42 } 43 } 44 int main() 45 { 46 n=read(),s1[0]=s2[0]=(data){-1,-1}; 47 for(int i=1;i<=n;i++) g[i].x=read(),g[i].y=read(); 48 sort(g+1,g+n+1,cmp); 49 cdq(1,n); 50 printf("%lld ",ans); 51 }