首先,x和y都小于一个向量且都大于一个向量的点一定是没有用的
这样就相当于挖掉了决策中位置偏中间的点,然后要求ax+by的最小值
设 ax+by=k,则 y=k/b-a/bx ,就变成了类似斜率优化的东西,相当于拿一个斜率去卡一个点
卡的点一定在凸包上,所以维护凸包,然后二分斜率查询就可以了
这个题要求支持查询历史版本的凸包,可以用线段树的思想,树分治的复杂度分析方法,将最终凸包2分成若干层独立凸包
然后由于答案是有凸包组成的,不会多点,所以直接在每个凸包上查询即可
非常难写,写代码一定要仔细
码:
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define zuo o<<1,l,mid
#define you o<<1|1,mid+1,r
#define eps 0.0000000000000005
#define N 400005
long double xx,yy,c,d;
long long daan;
int a,b,x,y,op,n,i,cnt;
bool wc[N<<2];
char lx,ch;
struct dian
{
long double x,y;
}q[N];
vector<dian>v[N<<2],v2[N<<2];
long double xl(dian a,dian b)
{
if(a.x==b.x)return 100000000000000007;
return (a.y-b.y)/(a.x-b.x);
}
void up(int o)
{
int ll=o<<1,rr=o<<1|1;
if(wc[ll]&&wc[rr]&&wc[o]==0)
{
int sx=v[ll].size()+v[rr].size(),zz=0,i,l1=0,l2=0;//上凸
for(i=1;i<=sx;i++)
{
dian d1,d2;
if(l1==v[ll].size())
{
d1.x=1000000000;d1.y=0;l1++;
}else d1=v[ll][l1],l1++;
if(l2==v[rr].size())
{
d2.x=1000000000;d2.y=0;l2++;
}else d2=v[rr][l2],l2++;
if(d1.x<d2.x||(d1.x==d2.x&&d1.y<d2.y))l2--;else l1--,swap(d1,d2);
while(zz>=2&&xl(d1,q[zz-1])+eps>xl(q[zz-1],q[zz]))zz--;
q[++zz]=d1;
}
for(i=1;i<=zz;i++)
v[o].push_back(q[i]);
sx=v2[ll].size()+v2[rr].size(),zz=0,i,l1=0,l2=0;//下凸
for(i=1;i<=sx;i++)
{
dian d1,d2;
if(l1==v2[ll].size())
{
d1.x=1000000000;d1.y=0;l1++;
}else d1=v2[ll][l1],l1++;
if(l2==v2[rr].size())
{
d2.x=1000000000;d2.y=0;l2++;
}else d2=v2[rr][l2],l2++;
if(d1.x<d2.x||(d1.x==d2.x&&d1.y<d2.y))l2--;else l1--,swap(d1,d2);
while(zz>=2&&xl(d1,q[zz-1])<xl(q[zz-1],q[zz])+eps)zz--;
q[++zz]=d1;
}
for(i=1;i<=zz;i++)
v2[o].push_back(q[i]);
wc[o]=1;
}
}
void gai(int o,int l,int r)
{
if(a<=l&&r<=b&&op==0)
{
dian lin;
lin.x=c;lin.y=d;
v[o].push_back(lin);
v2[o].push_back(lin);
wc[o]=1;
return ;
}
if(a<=l&&r<=b&&op==1&&wc[o])
{
if(yy>0)//找shang凸壳
{
int ll=1,rr=v[o].size()-1,ans=0;
c=max(c,xx*v[o][0].x+yy*v[o][0].y);
c=max(c,xx*v[o][rr].x+yy*v[o][rr].y);
while(ll<rr)
{
int mid=(ll+rr)>>1;
if(xl(v[o][mid],v[o][mid-1])+eps>-xx/yy)
{
ans=mid;
ll=mid+1;
}else rr=mid;
}
c=max(c,v[o][ans].x*xx+v[o][ans].y*yy);
}else//下凸壳
{
int ll=1,rr=v2[o].size()-1,ans=0;
c=max(c,xx*v2[o][0].x+yy*v2[o][0].y);
c=max(c,xx*v2[o][rr].x+yy*v2[o][rr].y);
while(ll<rr)
{
int mid=(ll+rr)>>1;
if(xl(v2[o][mid],v2[o][mid-1])<-xx/yy+eps)
{
ans=mid;
ll=mid+1;
}else rr=mid;
}
c=max(c,v2[o][ans].x*xx+v2[o][ans].y*yy);
}
return;
}
int mid=(l+r)>>1;
if(a<=mid)gai(zuo);
if(b>mid)gai(you);
up(o);
}
inline int decode (int x ) {
return x ^ (daan & 2147483647);
}
int main()
{
scanf("%d%c",&n,&lx);
while(lx==' ')scanf("%c",&lx);
for(i=1;i<=n;i++)
{
scanf("%c",&ch);while(ch!='A'&&ch!='Q')scanf("%c",&ch);
if(ch=='A')
{
scanf("%d%d",&x,&y);
if(lx!='E')x=decode(x),y=decode(y);
a=b=++cnt; op=0;c=x,d=y;
gai(1,1,n);
}
if(ch=='Q')
{
scanf("%d%d%d%d",&x,&y,&a,&b);
if(lx!='E')x=decode(x),y=decode(y),a=decode(a),b=decode(b);xx=x;yy=y;
op=1;c=-100000000000000007;
gai(1,1,n);
daan=c;
printf("%lld\n",daan);
}
}
}