JZOJ621720190614最大面积
Posted paul-guderian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JZOJ621720190614最大面积相关的知识,希望对你有一定的参考价值。
题意
平面上有\(n\)个点\(A_i\),\(q\)次询问,每次给出一个点\(P\),求:
\[
\sum_i=L^R 2S_\triangle OPA_i
\]
最大值,其中$S_\triangle_ABC ?= ?\frac\vecAB\times\vecAC 2 $为三角形的有向面积
$1 \le n \le 10^5 ?, ?1 \le q \le 10^6 $
题解
求出\(n^2\)个区间点和,求出他们构成的凸包
对于一个询问向量\((A,B)\),最优的点就是\((-A,-B)\)卡住的点(此时整个凸包在它左手边)
对于所有询问可以旋转卡壳\(O(q+n)\)完成
考虑如何求\(n^2\)个区间点和构成的凸包
对区间分治:考虑区间\([l,r]\) : 从\(mid\)向左做点后缀和,向右做点前缀和
对两边分别求凸包做\(minkowski\)和就得到了跨越\(mid\)区间点和的凸包,分治下去
这样得到的候选点的个数是\(n log \ n\)的,最后作一次总凸包
时间复杂度\(O(n \log ^2 n + q)\)
#include<bits/stdc++.h> #define il inline #define rg register #define ll long long using namespace std; const int N=2000010; int n,m,tot,tp;ll ans[N]; struct P ll x,y,z; P(ll _x=0,ll _y=0,ll _z=0):x(_x),y(_y),z(_z); P operator +(const P&a)constreturn P(x+a.x,y+a.y); P operator -(const P&a)constreturn P(x-a.x,y-a.y); bool operator <(const P&a)constreturn x==a.x?y<a.y:x<a.x; void rev()x=-x,y=-y; p[N],q[N],L[N],R[N],S[N],st[N]; ll crs(P a,P b)return a.x*b.y-a.y*b.x; void chkmin(ll&x,ll y)if(x>y)x=y; void chkmax(ll&x,ll y)if(x<y)x=y; char gc() static char*p1,*p2,s[1000000]; if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); return(p1==p2)?EOF:*p1++; int rd() int x=0,f=1;char c=gc(); while(c<'0'||c>'9')if(c=='-')f=-1;c=gc(); while(c>='0'&&c<='9')x=x*10+c-'0';c=gc(); return x*f; char ps[1000000],*pp=ps; void flush()fwrite(ps,1,pp-ps,stdout);pp=ps; void push(char x)if(pp==ps+1000000)flush();*pp++=x; void write(ll x) static int sta[20],top; if(x<0)push('-'),x=-x; if(!x)push('0');push('\n');return; while(x)sta[++top]=x%10,x/=10; while(top)push(sta[top--]^'0'); push('\n'); void convex(P*A,int&cnt) if(cnt==1)A[2]=A[1];return; sort(A+1,A+cnt+1); st[tp=1]=A[1]; for(int i=2;i<=cnt;++i) while(tp>1 && crs(st[tp]-st[tp-1],A[i]-st[tp])<=0 )tp--; st[++tp]=A[i]; int now=tp; for(int i=cnt-1;i;--i) while(tp>now && crs(st[tp]-st[tp-1],A[i]-st[tp])<=0 )tp--; st[++tp]=A[i]; cnt=0; for(int i=1;i<=tp;++i)if(!cnt||(st[i].x!=A[cnt].x||st[i].y!=A[cnt].y))A[++cnt]=st[i]; cnt--; void minkow(P*A,int cnt1,P*B,int cnt2) int j=1; for(int i=1;i<=cnt1;++i) S[++tot]=A[i]+B[j]; P now=A[i+1]-A[i]; while(j<=cnt2&&crs(B[j+1]-B[j],now)>=0)S[++tot]=A[i]+B[++j]; while(j<=cnt2)S[++tot]=A[1]+B[j++]; void solve(int l,int r) if(l==r)S[++tot]=p[l];return; int mid=(l+r)>>1,cnt1=0,cnt2=0; L[++cnt1]=R[++cnt2]=P(0,0); for(int i=mid;i>=l;--i)++cnt1,L[cnt1]=L[cnt1-1]+p[i]; for(int i=mid+1;i<=r;++i)++cnt2,R[cnt2]=R[cnt2-1]+p[i]; convex(L,cnt1);convex(R,cnt2); minkow(L,cnt1,R,cnt2); solve(l,mid);solve(mid+1,r); bool cmp(P a,P b) return crs(a,b)>0; //return atan2(a.y,a.x)<atan2(b.y,b.x); void calc() sort(q+1,q+m+1,cmp); int j=1,hd=1;while(!q[hd].x&&!q[hd].y)++hd; //while(tot>1&&crs(q[hd],S[j%tot+1]-S[j])<=0)j=j%tot+1; for(int i=1;i<=tot;++i)if(crs(q[hd],S[i]-S[j])<0)j=i; for(int i=1;i<=m;++i) if(!q[i].x&&!q[i].y)continue; while(tot>1&&crs(q[i],S[j%tot+1]-S[j])<=0)j=j%tot+1; ans[q[i].z]=-crs(q[i],S[j]); //查询答案的时候注意细节, 存在(0,0)....... int main() freopen("area.in","r",stdin); freopen("area.out","w",stdout); n=rd(),m=rd(); for(int i=1;i<=n;++i)p[i].x=rd(),p[i].y=rd(); int tmp=0; for(int i=1;i<=m;++i) q[++tmp].x=-rd(),q[tmp].y=-rd(),q[tmp].z=i; if(!q[tmp].x&&!q[tmp].y)tmp--; swap(tmp,m); solve(1,n); convex(S,tot); calc(); for(int i=1;i<=tmp;++i)write(ans[i]); return flush(),0; //
以上是关于JZOJ621720190614最大面积的主要内容,如果未能解决你的问题,请参考以下文章