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