这题其实并不怎么难,可是我现场没做出来QAQ,我还是太弱了,ORZ mjh,zyf dalao 们 tql!!!
很显然,我们可以将aix2+bixaix2+bix除以一个xx,得到,这时,要求aix2+bixaix2+bix,只需要在x>0x>0时求出最大的aix+biaix+bi,在x<0x<0时求出最小的aix+biaix+bi,在x=0x=0时输出00即可。
这就转化成了给定一堆直线,求出在与直线的交点的最高点或最低点。
那怎么做呢?我们先考虑x>0x>0的情况:首先,对于ai=ajai=aj,如果bi≥bjbi≥bj就不用考虑(aj,bj)(aj,bj)了,这时我们会发现对于不同的aiai,只有唯一的bibi与之对应(即最大值)。然后呢?我们又会发现,对于一个(ai,bi)(ai,bi),如果存在另一个(aj,bj)(aj,bj)使得aj≥aiaj≥ai且bj≥bibj≥bi,那么也不用考虑(ai,bi)(ai,bi)了。最后,我们会发现,剩下来的直线中,对于ai>ajai>aj,一定满足bi<bjbi<bj。我们按aiai从大到小排序,那么bibi递减。(由于数据范围很小,|ai|,|bi|,|x|≤32323|ai|,|bi|,|x|≤32323,所以直接桶排即可。)
现在我们又能发现一个性质,在这个顺序下,随着询问xx的递增,带来最优解的直线的下标一定是单调不下降的(这也非常好证明,因为是递增的,随着xx的增大,肯定是越右边带来的贡献越可能大),然后我发现这个最优解的位置并不好求,答案的判断并不满足单调性,于是我场上就想到这,GG。
当时一直困扰我的是这种情况:
会发现,当时,(a2,b2)(a2,b2)比(a1,b1)(a1,b1)更优,当x>b2−b3a3−a2x>b2−b3a3−a2时,(a3,b3)(a3,b3)比(a2,b2)(a2,b2)更优,但是由于b2−b3a3−a2<b1−b2a2−a1b2−b3a3−a2<b1−b2a2−a1,所以直接统计答案并不满足任何单调性,那怎么做呢?我们会发现,当x>b1−b3a3−a1x>b1−b3a3−a1时,(a3,b3)(a3,b3)比(a1,b1)(a1,b1)更优,又因为b1−b3a3−a1<b1−b2a2−a1b1−b3a3−a1<b1−b2a2−a1,所以(a3,b3)(a3,b3)先于(a2,b2)(a2,b2)变为可能的最优解,又因为前面证到最优解的下标随着xx的增加而不下降,所以永远不可能成为最优解,可以直接舍去。再仔细观察,我们发现其实这也正是一个求解凸包的过程,所以由此能得出结论,最优解一定在上凸壳上,将xx代入上凸壳上的每条直线得到的是一个单峰函数,可以直接二分或者用单调性扫一遍(其实不用这个结论一样做QWQ)。这样的情况就做完了。x<0x<0直接反着来即可。
由于使用了桶排序,所以时间复杂度为Θ(n+q+64647)Θ(n+q+64647) ,是线性的(实际上并没有跑多快QAQ)。
蒟蒻的暂时是全oj最快的代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int base=32323;
inline void read(int &x)
{
x=0;
bool f=false;
char ch=getchar();
while(!isdigit(ch))f^=(ch=='-'),ch=getchar();
while(isdigit(ch))x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
if(f)x=-x;
}
struct point{
int x,y;
};
int n,q;
int a[500010],b[500010];
int qa[500010];
bool has[70010];
point p[70010];
int mx[70010];
bool ok[70010];
long long ans[70010];
inline int calc(int x,point t){return t.x*x+t.y;}
inline void getmax(int &x,int y){x=x<y?y:x;}
void work(int coef)
{
for(int i=-base;i<=base;i++)mx[i+base]=-1e9;
for(int i=1;i<=n;i++)getmax(mx[(coef>0?a[i]:-a[i])+base],(coef>0?b[i]:-b[i]));
int tot=0;
for(int i=-base;i<=base;i++)if(mx[i+base]>-1e9)p[++tot]=(point){i,mx[i+base]};
int v=-1e9;
if(coef>0)
{
for(int i=tot;i>=1;i--)
{
if(v>=p[i].y)ok[i]=false;
else
{
ok[i]=true;
v=p[i].y;
}
}
}
else
{
for(int i=1;i<=tot;i++)
{
if(v>=p[i].y)ok[i]=false;
else
{
ok[i]=true;
v=p[i].y;
}
}
}
int cnt=0;
for(int i=1;i<=tot;i++)if(ok[i])p[++cnt]=p[i];
int top=1;
for(int i=2;i<=cnt;i++)
{
while(top>1 && 1LL*(p[i].x-p[top].x)*(p[top].y-p[top-1].y)<=1LL*(p[top].x-p[top-1].x)*(p[i].y-p[top].y))top--;
p[++top]=p[i];
}
int pos=1;
int l=coef>0?1:-base,r=coef>0?base:-1;
for(int i=l;i<=r;i++)
{
if(!has[i+base])continue;
while(pos<top && calc(i,p[pos+1])>=calc(i,p[pos]))pos++;
ans[i+base]=1LL*calc(i,p[pos])*i*coef;
}
}
int main()
{
read(n);read(q);
for(int i=1;i<=n;i++)read(a[i]),read(b[i]);
for(int i=1;i<=q;i++)read(qa[i]),has[qa[i]+base]=true;
work(1);
work(-1);
for(int i=1;i<=q;i++)printf("%lld\n",ans[qa[i]+base]);
return 0;
}