卡时限过去
(多刷几次就好啦
凸壳分成四块 扫描线加线段树处理边界点
根据预处理的边界点之间凸壳面积计算
面积计算以原点为三角形的第三个节点 注意每一块面积对答案的贡献是正的还是负的
这题居然花了我一天时间
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define abs(a) ((a)<0?-(a):(a))
#define ll long long
ll A[3001][3001],B[3001][3001],C[3001][3001],D[3001][3001];
struct Flag
{
int a,b;
Flag(){};
Flag(int a,int b):a(a),b(b){}
inline friend Flag operator +(Flag a,Flag b){return a.b>b.b?a:b;}
inline friend bool operator !=(Flag a,Flag b){return a.b^b.b;}
};
Flag NUL=Flag(-1,-1);
struct Node
{
Flag A,f;
int l,r;
Node *lc,*rc;
Node():f(NUL),A(NUL),lc(NULL),rc(NULL){};
Node(int x,int y):l(x),r(y),A(NUL),lc(NULL),rc(NULL),f(NUL){};
}Q7[1000001];
int Cnt;
inline Node *Build(int l,int r){Q7[++Cnt]=Node(l,r);return Q7+Cnt;}
inline void pushdown(Node *Cur)
{
if(Cur->lc==NULL)Cur->lc=Build(Cur->l,Cur->l+Cur->r>>1),Cur->rc=Build((Cur->l+Cur->r>>1)+1,Cur->r);
Cur->lc->A=Cur->rc->A=Cur->lc->f=Cur->rc->f=Cur->f;
Cur->f=NUL;
}
inline void Update(Node *Cur,int l,Flag Delt)
{
if(!Cur)return;
if(Cur->l>=l&&l>=Cur->r){Cur->A=Cur->f=Delt;return;}
if(Cur->f!=NUL)pushdown(Cur);
Cur->A=Delt;
int mid=Cur->l+Cur->r>>1;
if(!Cur->lc)
Cur->lc=Build(Cur->l,mid),Cur->rc=Build(mid+1,Cur->r);
if(l<=mid)Update(Cur->lc,l,Delt);
else Update(Cur->rc,l,Delt);
}
Flag Query(Node *Cur,int l,int r)
{
if(!Cur)return NUL;
int mid=Cur->l+Cur->r>>1;
if(l<=Cur->l&&r>=Cur->r)return Cur->A;
Flag res=NUL;
if(l<=mid)res=res+Query(Cur->lc,l,r);
if(r>mid)res=res+Query(Cur->rc,l,r);
return res+Cur->f;
}
struct P
{
int x,y,i;
P(){}
P(int x,int y):x(x),y(y){}
inline friend ll operator *(P a,P b){return a.x*1ll*b.y-a.y*1ll*b.x;}
inline friend P operator -(P a,P b){return P(a.x-b.x,a.y-b.y);}
}L[3001];
inline bool cmp1(P a,P b){return a.x^b.x?a.x<b.x:a.y<b.y;}
inline bool cmp2(P a,P b){return a.x^b.x?a.x<b.x:a.y>b.y;}
inline bool cmp3(P a,P b){return a.x^b.x?a.x>b.x:a.y<b.y;}
inline bool cmp4(P a,P b){return a.x^b.x?a.x>b.x:a.y>b.y;}
inline bool cmp5(P a,P b){return a.x^b.x?a.x<b.x:a.y<b.y;}
inline bool cmp6(P a,P b){return a.y^b.y?a.y<b.y:a.x<b.x;}
inline bool cmp7(P a,P b){return a.x^b.x?a.x>b.x:a.y>b.y;}
inline bool cmp8(P a,P b){return a.y^b.y?a.y>b.y:a.x>b.x;}
struct Q
{
int P;
int no;
}sx[1000001],ex[1000001],sy[1000001],ey[1000001];
int EX[1000001],EY[1000001],SX[1000001],SY[1000001];
int Ex[1000001],Ey[1000001],Sx[1000001],Sy[1000001];
bool Ans[1000001];
inline bool cmps(Q a,Q b){return a.P<b.P;}
inline bool cmpe(Q a,Q b){return a.P>b.P;}
P Bl=P(-0,-0);
char c;
bool flag;
inline void read(int &a)
{a=0;do c=getchar(); while(c!='-'&&(c<'0'||c>'9'));c=c=='-'?flag=true,getchar():c;while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();a=flag?flag=false,-a:a;}
int stack[100001],top;
int main()
{
int n,k;
read(k),read(n);
for(int i=1;i<=n;i++)read(L[i].x),read(L[i].y),L[i].i=i;
sort(L+1,L+1+n,cmp1);
for(int i=1;i<n;i++)
{
stack[top=1]=i;
for(int j=i+1;j<=n;j++)if(L[j].y>=L[i].y)
{
while(top>1&&(L[stack[top]]-L[stack[top-1]])*(L[j]-L[stack[top-1]])<=0)top--;
stack[++top]=j;
A[L[i].i][L[j].i]=L[stack[top-1]]*L[stack[top]]+A[L[i].i][L[stack[top-1]].i];
}
}
sort(L+1,L+1+n,cmp2);
for(int i=1;i<n;i++)
{
stack[top=1]=i;
for(int j=i+1;j<=n;j++)if(L[j].y<=L[i].y)
{
while(top>1&&(L[stack[top]]-L[stack[top-1]])*(L[j]-L[stack[top-1]])>=0)top--;
stack[++top]=j;
B[L[i].i][L[j].i]=L[stack[top-1]]*L[stack[top]]+B[L[i].i][L[stack[top-1]].i];
}
}
sort(L+1,L+1+n,cmp3);
for(int i=1;i<n;i++)
{
stack[top=1]=i;
for(int j=i+1;j<=n;j++)if(L[j].y>=L[i].y)
{
while(top>1&&(L[stack[top]]-L[stack[top-1]])*(L[j]-L[stack[top-1]])>=0)top--;
stack[++top]=j;
C[L[i].i][L[j].i]=L[stack[top-1]]*L[stack[top]]+C[L[i].i][L[stack[top-1]].i];
}
}
sort(L+1,L+1+n,cmp4);
for(int i=1;i<n;i++)
{
stack[top=1]=i;
for(int j=i+1;j<=n;j++)if(L[j].y<=L[i].y)
{
while(top>1&&(L[stack[top]]-L[stack[top-1]])*(L[j]-L[stack[top-1]])<=0)top--;
stack[++top]=j;
D[L[i].i][L[j].i]=L[stack[top-1]]*L[stack[top]]+D[L[i].i][L[stack[top-1]].i];
}
}
int m;
read(m);
for(int i=1;i<=m;i++)
read(sx[i].P),read(ex[i].P),read(sy[i].P),read(ey[i].P),
sx[i].no=sy[i].no=ex[i].no=ey[i].no=i,
Sx[i]=sx[i].P,Sy[i]=sy[i].P,Ex[i]=ex[i].P,Ey[i]=ey[i].P;
sort(L+1,L+1+n,cmp6);
sort(ey+1,ey+1+m,cmps);
int j=1;
Cnt=0;
Node *MYT=Build(0,k);
for(int i=1;i<=m;i++)
{
while(j<=n&&L[j].y<=ey[i].P)Update(MYT,L[j].x,Flag(L[j].i,j)),j++;
Flag T;
EY[ey[i].no]=(T=Query(MYT,Sx[ey[i].no],Ex[ey[i].no])).a;
if(T.b==-1||Sy[ey[i].no]>L[T.b].y)Ans[ey[i].no]=true;
}Cnt=0;
MYT=Build(0,k);
sort(L+1,L+1+n,cmp8);
sort(sy+1,sy+1+m,cmpe);
j=1;
for(int i=1;i<=m;i++)
{
while(j<=n&&L[j].y>=sy[i].P)Update(MYT,L[j].x,Flag(L[j].i,j)),j++;
Flag T;
SY[sy[i].no]=(T=Query(MYT,Sx[sy[i].no],Ex[sy[i].no])).a;
if(T.b==-1||Ey[sy[i].no]<L[T.b].y)Ans[sy[i].no]=true;
}Cnt=0;
MYT=Build(0,k);
sort(L+1,L+1+n,cmp5);
sort(ex+1,ex+1+m,cmps);
j=1;
for(int i=1;i<=m;i++)
{
while(j<=n&&L[j].x<=ex[i].P)Update(MYT,L[j].y,Flag(L[j].i,j)),j++;
Flag T;
EX[ex[i].no]=(T=Query(MYT,Sy[ex[i].no],Ey[ex[i].no])).a;
if(T.b==-1||Sx[ex[i].no]>L[T.b].x)Ans[ex[i].no]=true;
}
sort(L+1,L+1+n,cmp7);
sort(sx+1,sx+1+m,cmpe);
j=1;Cnt=0;
MYT=Build(0,k);
for(int i=1;i<=m;i++)
{
while(j<=n&&L[j].x>=sx[i].P)Update(MYT,L[j].y,Flag(L[j].i,j)),j++;
Flag T;
SX[sx[i].no]=(T=Query(MYT,Sy[sx[i].no],Ey[sx[i].no])).a;
if(T.b==-1||Ex[sx[i].no]<L[T.b].x)Ans[sx[i].no]=true;
}
for(int i=1;i<=m;i++)
{
ll ans=0;
if(SY[i]==-1||EY[i]==-1||EX[i]==-1||SX[i]==-1){puts("0.0");continue;}
if(Ans[i]){puts("0.0");continue;}
ans=A[SY[i]][EX[i]]-B[EY[i]][EX[i]]-C[SY[i]][SX[i]]+D[EY[i]][SX[i]];
printf("%lld.%d\n",ans>>1,ans&1?5:0);
}
return 0;
}