我咋还没找到
题意
给定
题解
记
设
如果给定
然后我们枚举
后缀凸包其实就是从后往前建凸包,往栈里加点和删点就等价于是在树上新增一个儿子或者跳回父亲,最后得到一棵
当然这样单次询问
代码
const int N=5e3+10,L=1e5,M=L+10,K=18;
const int inf=0x3f3f3f3f;
int n,m,T,mx,x[N],a[N],y[N],b[N];
int va[M],vb[M],fa[M][K];ll c;
struct point{
int x,y;point(int x=0,int y=0):x(x),y(y){}
point operator-(point rhs){return point(x-rhs.x,y-rhs.y);}
ll operator*(point rhs){return 1ll*x*rhs.y-1ll*y*rhs.x;}
}st[M];int top;
ll get(int i,int j){return 1ll*i*vb[j]+1ll*j*va[i];}
bool chk(int i,int j){
// x>=j i bx + x ai 的最小值
for(int l=K-1;~l;l--)if(fa[fa[j][l]][0]&&get(i,fa[j][l])>=get(i,fa[fa[j][l]][0]))j=fa[j][l];
if(fa[j][0]&&get(i,fa[j][0])<=c)return 1;
return get(i,j)<=c;
}
void work(){
ll ans=0;
for(int j=1,i=L;j<=L&&i;)
if(vb[j]==inf)j++;
else if(va[i]==inf||!chk(i,j))i--;
else chkmx(ans,1ll*i*j),j++;
writeln(ans);
}
signed main(){
read(n,m,T);memset(va,0x3f,sizeof va);memset(vb,0x3f,sizeof vb);
readArr(x+1,n);readArr(a+1,n);readArr(y+1,m);readArr(b+1,m);
for(int i=1;i<n;i++)for(int j=i+1;j<=n;j++)chkmn(va[x[j]-x[i]],a[i]+a[j]);
for(int i=1;i<m;i++)for(int j=i+1;j<=m;j++)chkmn(vb[y[j]-y[i]],b[i]+b[j]);
for(int i=L;i;i--)if(vb[i]!=inf){
point p(i,vb[i]);
while(top>=2&&(st[top]-p)*(st[top-1]-p)<=0)top--;
if(top)fa[i][0]=st[top].x;
st[++top]=p;
}
for(int i=1;i<K;i++)for(int j=1;j<=L;j++)fa[j][i]=fa[fa[j][i-1]][i-1];
while(T--)read(c),work();
}