説明
入力
出力
サンプル入力
2 4
3 0
4 -2
-1
0
1
2
サンプル出力
6
0
3
12
データ制約
思考
何定数項がないので、同時にXによって分割することができ、方程式は次のようになる。Y = AX + B
二部上のx> 0凸包のために
二部でのx「0凸包の場合
コード
#include <bits/stdc++.h>
using namespace std;
#define pii pair <int,int>
#define LL long long
const int N = 6e5;
int n,q;
pii Eu[N],Ed[N],Su[N],Sd[N];
int cntu,cntd;
void work(pii E[],int n,pii S[],int &cnt)
{
sort(E + 1,E + n + 1);
for (int i = 1; i <= n; ++ i)
{
while (
cnt >= 1 && S[cnt].first == E[i].first ||
cnt >= 2 &&
1ll * (S[cnt - 1].second - S[cnt].second) * (E[i].first - S[cnt - 1].first) >=
1ll * (S[cnt - 1].second - E[i].second) * (S[cnt].first - S[cnt - 1].first))
cnt --;
S[++ cnt] = E[i];
}
}
int calc(pii a,int x)
{
return a.first * x + a.second;
}
LL find_max(pii S[],int cnt,int x)
{
int l = 1,r = cnt;
while (l < r)
{
int m = (l + r) / 2;
if (calc(S[m],x) > calc(S[m + 1],x))
r = m;
else l = m + 1;
}
return 1ll * calc(S[l],x) * x;
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d%d",&n,&q);
for (int i = 1; i <= n; ++ i)
{
int a,b;
scanf("%d%d",&a,&b);
Eu[i] = make_pair(a,b);
Ed[i] = make_pair(-a,-b);
}
work(Eu,n,Su,cntu);
work(Ed,n,Sd,cntd);
while (q --)
{
int x;
scanf("%d",&x);
if (x == 0) puts("0");
else if (x > 0) printf("%lld\n",find_max(Su,cntu,x));
else printf("%lld\n",-find_max(Sd,cntd,x));
}
}