把叉积拆开,区间和转化为前缀和
然后前缀和就是
f
[
i
]
=
∑
x
i
∗
y
−
∑
y
i
∗
x
f[i]=\sum{xi}*y-\sum{yi}*x
f[i]=∑xi∗y−∑yi∗x
要求一个j使得
f
[
i
]
−
f
[
j
]
f[i]-f[j]
f[i]−f[j]最大(最小一样的)
那就是
(
∑
x
i
∗
y
−
∑
y
i
∗
x
)
−
(
∑
x
j
∗
y
−
∑
y
j
∗
x
)
(\sum{xi}*y-\sum{yi}*x)-(\sum{xj}*y-\sum{yj}*x)
(∑xi∗y−∑yi∗x)−(∑xj∗y−∑yj∗x)
移项得
(
∑
x
i
−
∑
x
j
)
∗
y
−
(
∑
y
i
−
∑
y
j
)
∗
x
(\sum{xi}-\sum{xj})*y-(\sum{yi}-\sum{yj})*x
(∑xi−∑xj)∗y−(∑yi−∑yj)∗x
即
y
x
≥
∑
y
i
−
∑
y
j
∑
x
i
−
∑
x
j
\frac{y}{x}\ge\frac{\sum{yi}-\sum{yj}}{\sum{xi}-\sum{xj}}
xy≥∑xi−∑xj∑yi−∑yj
那就按斜率在凸壳上二分就完了
Code:
#include<bits/stdc++.h>
#define db double
#define int long long
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=1e6+5;
struct point{
int x,y;
point(){}
point(int _x,int _y):x(_x),y(_y){}
friend inline point operator + (const point &a,const point &b){return point(a.x+b.x,a.y+b.y);}
friend inline point operator - (const point &a,const point &b){return point(a.x-b.x,a.y-b.y);}
friend inline int operator * (const point &a,const point &b){return a.x*b.y-a.y*b.x;}
}a[N],b[N],p[N];
int tota=0,totb=0;
int n;
inline void graham(){
a[tota=1]=point(0,0);a[++tota]=p[1];
b[totb=1]=point(0,0);b[++totb]=p[1];
for(int i=2;i<=n;i++){
while(tota>=2 && (a[tota]-a[tota-1])*(p[i]-a[tota-1])>=0) --tota;
a[++tota]=p[i];
while(totb>=2 && (p[i]-b[totb-1])*(b[totb]-b[totb-1])>=0) --totb;
b[++totb]=p[i];
}
}
inline db calc(point a,db k){return a.y-a.x*k;}
inline db check1(db x){
int l=1,r=tota;
int ans=1;
while(l<=r){
int mid=(l+r)>>1;
if(calc(a[mid],x)>=calc(a[mid+1],x)) r=mid-1,ans=mid;
else l=mid+1;
}
return calc(a[ans],x);
}
inline db check2(db x){
int l=1,r=totb;
int ans=1;
while(l<=r){
int mid=(l+r)>>1;
if(calc(b[mid+1],x)>=calc(b[mid],x)) r=mid-1,ans=mid;
else l=mid+1;
}
return calc(b[ans],x);
}
signed main(){
n=read();
p[0]=point(0,0);
for(int x,y,i=1;i<=n;i++){
x=read(),y=read();
p[i]=p[i-1]+point(x,y);
}
graham();
int q=read();
while(q--){
int x=read(),y=read();
db k=(db)y/x;
db f1=check1(k),f2=check2(k);
cout<<(int)round(x*(f1-f2))<<"\n";
}
return 0;
}