题目描述
平面上有n个不重复的点。每次询问一个边平行坐标轴的矩形内(包含边界)的点组成的凸包的面积。、
输入格式
第一行两个整数k,n(1<=k<=1000000,3<=n<=3000)。
接下来n行,每行两个整数x_i,y_i(0<=x_i,y_i<=k),表示点的坐标。
接下来一行一个整数m(1<=m<=1000000),表示询问数量。
接下来m行,每行四个整数a,b,c,d(0<=a<b<=k,0<=c<d<=k),表示询问的矩形范围为a<=x<=b,c<=y<=d。
输出格式
对于每个询问输出一行表示面积。保留小数点后一位。
-
题解
- 和这里的方向处理有点略微不同;
- 可以用排序扫描线+线段树维护出矩形边框四个方向可以卡住的切点,从南逆时针记为:$Ns,Ne,Nn,Nw$;
- $O(n^2)A$处理出一个点沿四个象限伸展且横纵坐标均单调的凸包,并处理出从沿凸包从$A$走到$B$的叉积和;
- 沿着$Ns,Ne,Nn,Nw$绕一圈查询对应象限的叉积和就$O(1)$求出面积;
- 由于一三,二四象限一定不会有交集所以可以分别存在一起;
- 注意由于要维护叉积求凸包的排序要有优先级;
- 算了说不清楚,。。。,还是去看Claris的题解吧。。。。。。TAT
- 和这里的方向处理有点略微不同;
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define il inline 4 #define ls (k<<1) 5 #define rs (k<<1|1) 6 using namespace std; 7 const int N=3010,M=1000010; 8 int n,m,q,Ne[M],Nw[M],Nn[M],Ns[M],top,T[N]; 9 int mx[M<<2]; 10 ll A[N][N],B[N][N]; 11 struct poi{ 12 int x,y,z,w; 13 poi(int _x=0,int _y=0,int _z=0,int _w=0):x(_x),y(_y),z(_z),w(_w){}; 14 poi operator -(const poi&a){return poi(x-a.x,y-a.y);} 15 }P[N],Q[M],que[N]; 16 struct data{int a,b,c,d;}D[M]; 17 il bool cmp1(const poi&a,const poi&b){return a.x==b.x?a.y<b.y:a.x<b.x;} 18 il bool cmp2(const poi&a,const poi&b){return a.y==b.y?a.x>b.x:a.y<b.y;} 19 il bool cmpx(const poi&a,const poi&b){return /*a.x==b.x?a.y<b.y:*/a.x<b.x;} 20 il bool cmpy(const poi&a,const poi&b){return /*a.y==b.y?a.x>b.x:*/a.y<b.y;} 21 il char gc(){ 22 static char*p1,*p2,s[1000000]; 23 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 24 return(p1==p2)?EOF:*p1++; 25 } 26 il int rd(){ 27 int x=0; char c=gc(); 28 while(c<'0'||c>'9')c=gc(); 29 while(c>='0'&&c<='9'){x=x*10+c-'0';c=gc();} 30 return x; 31 } 32 ll crs(poi a,poi b){return (ll)a.x*b.y-(ll)a.y*b.x;} 33 il int Max(int a,int b){return T[a]<T[b]?b:a;} 34 il int query(int k,int l,int r,int x,int y){ 35 if(l==x&&r==y)return mx[k]; 36 else { 37 int mid=(l+r)>>1; 38 if(y<=mid)return query(ls,l,mid,x,y); 39 else if(x>mid)return query(rs,mid+1,r,x,y); 40 else return Max(query(ls,l,mid,x,mid),query(rs,mid+1,r,mid+1,y)); 41 } 42 } 43 il void update(int k,int l,int r,int x,int v){ 44 if(l==r)mx[k]=v; 45 else{ 46 mx[k]=v; 47 int mid=(l+r)>>1; 48 if(x<=mid)update(ls,l,mid,x,v); 49 else update(rs,mid+1,r,x,v); 50 } 51 } 52 void build(int k,int l,int r){ 53 mx[k]=0; 54 if(l==r){T[l]=0;return;} 55 int mid=(l+r)>>1; 56 build(ls,l,mid); 57 build(rs,mid+1,r); 58 } 59 int main(){ 60 freopen("bzoj3839.in","r",stdin); 61 freopen("bzoj3839.out","w",stdout); 62 n=rd(); m=rd(); 63 for(int i=1;i<=m;++i)P[i].x=rd(),P[i].y=rd(),P[i].z=i; 64 65 sort(P+1,P+m+1,cmp1); 66 for(int i=1;i<=m;++i){ 67 que[top=1]=P[i]; 68 for(int j=i-1;j;--j)if(P[j].y<=P[i].y){ 69 while(top>1&&crs(que[top]-que[top-1],P[j]-que[top])<=0)top--; 70 que[++top]=P[j]; 71 A[P[i].z][P[j].z]=A[P[i].z][que[top-1].z]+crs(que[top-1],P[j]); 72 } 73 que[top=1]=P[i]; 74 for(int j=i+1;j<=m;++j)if(P[j].y>=P[i].y){ 75 while(top>1&&crs(que[top]-que[top-1],P[j]-que[top])<=0)top--; 76 que[++top]=P[j]; 77 A[P[i].z][P[j].z]=A[P[i].z][que[top-1].z]+crs(que[top-1],P[j]); 78 } 79 } 80 sort(P+1,P+m+1,cmp2); 81 for(int i=1;i<=m;++i){ 82 que[top=1]=P[i]; 83 for(int j=i-1;j;--j)if(P[j].x>=P[i].x){ 84 while(top>1&&crs(que[top]-que[top-1],P[j]-que[top])<=0)top--; 85 que[++top]=P[j]; 86 B[P[i].z][P[j].z]=B[P[i].z][que[top-1].z]+crs(que[top-1],P[j]); 87 } 88 que[top=1]=P[i]; 89 for(int j=i+1;j<=m;++j)if(P[j].x<=P[i].x){ 90 while(top>1&&crs(que[top]-que[top-1],P[j]-que[top])<=0)top--; 91 que[++top]=P[j]; 92 B[P[i].z][P[j].z]=B[P[i].z][que[top-1].z]+crs(que[top-1],P[j]); 93 } 94 } 95 96 q=rd();for(int i=1;i<=q;++i)D[i].a=rd(),D[i].b=rd(),D[i].c=rd(),D[i].d=rd(); 97 98 sort(P+1,P+m+1,cmpx); 99 for(int i=1;i<=q;++i)Q[i]=(poi){D[i].a,D[i].c,D[i].d,i}; 100 sort(Q+1,Q+q+1,cmpx); 101 build(1,0,n); 102 for(int i=q,j=m;i;--i){ 103 while(j&&P[j].x>=Q[i].x)T[P[j].z]=m-j+1,update(1,0,n,P[j].y,P[j].z),j--; 104 Nw[Q[i].w]=query(1,0,n,Q[i].y,Q[i].z); 105 } 106 107 for(int i=1;i<=q;++i)Q[i]=(poi){D[i].b,D[i].c,D[i].d,i}; 108 sort(Q+1,Q+q+1,cmpx); 109 build(1,0,n); 110 for(int i=1,j=1;i<=q;++i){ 111 while(j<=m&&P[j].x<=Q[i].x)T[P[j].z]=j,update(1,0,n,P[j].y,P[j].z),j++; 112 Ne[Q[i].w]=query(1,0,n,Q[i].y,Q[i].z); 113 } 114 115 sort(P+1,P+m+1,cmpy); 116 for(int i=1;i<=q;++i)Q[i]=(poi){D[i].c,D[i].a,D[i].b,i}; 117 sort(Q+1,Q+q+1,cmpx); 118 build(1,0,n); 119 for(int i=q,j=m;i;--i){ 120 while(j&&P[j].y>=Q[i].x)T[P[j].z]=m-j+1,update(1,0,n,P[j].x,P[j].z),j--; 121 Ns[Q[i].w]=query(1,0,n,Q[i].y,Q[i].z); 122 } 123 124 for(int i=1;i<=q;++i)Q[i]=(poi){D[i].d,D[i].a,D[i].b,i}; 125 sort(Q+1,Q+q+1,cmpx); 126 build(1,0,n); 127 for(int i=1,j=1;i<=q;++i){ 128 while(j<=m&&P[j].y<=Q[i].x)T[P[j].z]=j,update(1,0,n,P[j].x,P[j].z),j++; 129 Nn[Q[i].w]=query(1,0,n,Q[i].y,Q[i].z); 130 } 131 for(int i=1;i<=q;++i){ 132 ll ans = A[Ns[i]][Ne[i]] + B[Ne[i]][Nn[i]] + A[Nn[i]][Nw[i]] + B[Nw[i]][Ns[i]]; 133 // printf("%lld %lld %lld %lld ",A[Nn[i]][Nw[i]],B[Ne[i]][Nn[i]],B[Nw[i]][Ns[i]],A[Ns[i]][Ne[i]]); 134 // printf("%d %d %d %d ",Nn[i],Nw[i],Ns[i],Ne[i]); 135 printf("%.1lf ",ans/2.0); 136 } 137 return 0; 138 }