Description
Solution
把式子的绝对值去掉就变成了一道维护直线的题面了,
这个直接用线段树即可,
像主席树那样,不下传标记,每个点都表示这一条线段,表示线段在这个区间可能会是某些坐标的最优值,
每次加入一条线段,就判断一下这条线是否在这个区间内都是由于原来的线段,否则看看是那一边比原来的优就往哪边走(可能两边都走),
询问只是一个点,所以只要看一下访问路径上的所有直线计算最大值即可,
复杂度 O(nlog(n))
Code
#include <cstdio>
#include <algorithm>
#include <iostream>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
#define SU(k,b,x) ((LL)(k)*(LL)(x)+(LL)(b))
#define mxSU(k,b,l,r) (max(SU(k,b,l),SU(k,b,r)))
#define miSU(k,b,l,r) (min(SU(k,b,l),SU(k,b,r)))
using namespace std;
typedef long long LL;
const int N=200500,INF=-1e9;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n;
LL Ans[N];
struct qwqw
{
int k,b,i;
}a1[N],a[N];
bool PX(qwqw q,qwqw w){return q.k<w.k;}
struct qqww
{
int l,r,k,b;
}b[N*4];
int root,b0;
void change(int l,int r,int &e,int lk,int lb)
{
if(!e)b[e=++b0]=b[0];
LL tl=SU(b[e].k,b[e].b,l),tr=SU(b[e].k,b[e].b,r);
LL ll=SU(lk,lb,l),lr=SU(lk,lb,r);
if(tl>=ll&&tr>=lr)return;
if(tl<=ll&&tr<=lr)
{
b[e].k=lk,b[e].b=lb;
return;
}
int t=(l+r)>>1;
if(tl<ll||(SU(b[e].k,b[e].b,t)<SU(lk,lb,t)))change(l,t,b[e].l,lk,lb);
if((tr<lr)||(SU(b[e].k,b[e].b,t+1)<SU(lk,lb,t+1)))change(t+1,r,b[e].r,lk,lb);
}
LL find(int l,int r,int e,int l1)
{
if(b[e].k==INF&&b[e].b==INF)return -1e18;
if(l==r)return SU(b[e].k,b[e].b,l);
int t=(l+r)>>1;
LL ans;
if(l1<=t)ans=find(l,t,b[e].l,l1);
else ans=find(t+1,r,b[e].r,l1);
ans=max(ans,SU(b[e].k,b[e].b,l1));
return ans;
}
int main()
{
freopen("gas.in","r",stdin);
freopen("gas.out","w",stdout);
int q,w,mx=0;
read(m),read(n);
fo(i,1,m)read(a1[i].k),read(a1[i].b);
fo(i,1,n)read(a[i].k),read(a[i].b),mx=max(mx,a[i].b),a[i].i=i;
sort(a1+1,a1+1+m,PX);
sort(a+1,a+1+n,PX);
b[0].k=b[0].b=INF;
a[n+1].k=a1[m+1].k=2e9;
root=b0=0;
for(int i=1,j=1;i<=n||j<=m;)
{
if(a[i].k<a1[j].k)
{
Ans[a[i].i]=find(1,mx,root,a[i].b)-(LL)a[i].k*a[i].b;
i++;
}else
{
change(1,mx,root,a1[j].k,a1[j].b);
j++;
}
}
a[0].k=a1[0].k=-2e9;
root=b0=0;
for(int i=n,j=m;i||j;)
{
if(a[i].k>a1[j].k)
{
LL t=find(1,mx,root,a[i].b)+(LL)a[i].k*a[i].b;
Ans[a[i].i]=max(t,Ans[a[i].i]);
i--;
}else
{
change(1,mx,root,-a1[j].k,a1[j].b);
j--;
}
}
fo(i,1,n)printf("%lld\n",max(0,Ans[i]));
return 0;
}