由点积的几何意义(即投影)可以发现答案一定在凸壳上,并且投影的变化是一个单峰函数,可以三分。现在需要处理的只有删除操作,线段树分治即可。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 200010
#define ll long long
int n,m,t;
int L[N<<],R[N<<],size[N<<];
struct point
{
int x,y,s;
ll operator *(const point&a) const
{
return 1ll*x*a.x+1ll*y*a.y;
}
bool operator <(const point&a) const
{
return x<a.x;
}
}a[N],q[N];
bool check(point a,point b,point c)
{
return 1ll*(a.y-b.y)*(c.x-b.x)>1ll*(c.y-b.y)*(a.x-b.x);
}
vector<point> tree[N<<];
void build(int k,int l,int r)
{
L[k]=l,R[k]=r;
if (l==r) return;
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
}
void ins(int k,int l,int r,point x)
{
if (L[k]==l&&R[k]==r) {tree[k].push_back(x);return;}
int mid=L[k]+R[k]>>;
if (r<=mid) ins(k<<,l,r,x);
else if (l>mid) ins(k<<|,l,r,x);
else ins(k<<,l,mid,x),ins(k<<|,mid+,r,x);
}
void make(int k)
{
sort(tree[k].begin(),tree[k].end());
int s=tree[k].size(),t=-;
for (int i=;i<s;i++)
{
while (t>=&&tree[k][i].y>tree[k][t].y) t--;
while (t>&&check(tree[k][t-],tree[k][t],tree[k][i])) t--;
tree[k][++t]=tree[k][i];
}
size[k]=t;
if (L[k]==R[k]) return;
make(k<<),make(k<<|);
}
ll calc(int k,point x)
{
if (size[k]==-) return ;
int l=,r=size[k];
while (l+<r)
{
int mid1=l+(r-l)/,mid2=r-(r-l)/;
if (x*tree[k][mid1]>x*tree[k][mid2]) r=mid2;
else l=mid1;
}
ll ans=;
for (int i=l;i<=r;i++) ans=max(ans,x*tree[k][i]);
return ans;
}
ll query(int k,int p,point x)
{
ll t=calc(k,x);
if (L[k]==R[k]) return t;
int mid=L[k]+R[k]>>;
if (p<=mid) return max(t,query(k<<,p,x));
else return max(t,query(k<<|,p,x));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4311.in","r",stdin);
freopen("bzoj4311.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
build(,,n);
for (int i=;i<=n;i++)
{
int op=read();
if (op==) t++,a[t].x=read(),a[t].y=read(),a[t].s=i;
else if (op==) m++,q[m].x=read(),q[m].y=read(),q[m].s=i;
else
{
int x=read();
ins(,a[x].s,i,a[x]);
a[x].x=a[x].y=;
}
}
for (int i=;i<=t;i++)
if (a[i].x) ins(,a[i].s,n,a[i]);
make();
for (int i=;i<=m;i++) printf(LL,query(,q[i].s,q[i]));
return ;
}