bzoj3839【Pa2013】Działka

题目描述

平面上有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 }
bzoj3839
原文地址:https://www.cnblogs.com/Paul-Guderian/p/10285812.html