题目
解法
假设向量 \((x_2,y_2)\) 对于询问 \((x,y)\) 优于 \((x_1,y_1)\),其中 \(x_1<x_2\)。那么有:
\[x_1x+y_1y<x_2x+y_2y
\]
\[-\frac{x}{y}<\frac{y_2-y_1}{x_2-x_1}
\]
所以我们需要维护一个斜率递减的凸包。考虑三个点 \(i<j<k\),如果斜率递增,\(j\) 优于 \(i\) 时 \(k\) 一定优于 \(j\),所以 \(j\) 是不必要的。
维护每个向量的存在区间然后线段树分治。可以对于询问 \((x,y)\) 在凸包上二分。也可以将询问按 \(-\frac{x}{y}\) 从大到小排序,这个可以用归并排序。然后用双指针扫一遍就行了。
时间复杂度 \(\mathcal O(n\log n)\)。
代码
#include <cstdio>
#define print(x,y) write(x),putchar(y)
template <class T>
inline T read(const T sample) {
T x=0; char s; bool f=0;
while((s=getchar())>'9' or s<'0')
f|=(s=='-');
while(s>='0' and s<='9')
x=(x<<1)+(x<<3)+(s^48),
s=getchar();
return f?-x:x;
}
template <class T>
inline void write(const T x) {
if(x<0) {
putchar('-'),write(-x);
return;
}
if(x>9) write(x/10);
putchar(x%10^48);
}
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
int n,m,tmp[maxn],tp;
int p[maxn];
ll ans[maxn];
struct node {
int x,y,l,r;
bool operator < (const node &t) const {
return x<t.x;
}
} vec[maxn];
struct Node {
int x,y;
Node operator - (const Node &t) const {
return (Node){x-t.x,y-t.y};
}
} q[maxn],stk[maxn];
vector <Node> g[maxn<<2];
void ins(int o,int l,int r,const node &v) {
if(l>v.r or r<v.l) return;
if(l>=v.l and r<=v.r)
return (void)(g[o].push_back((Node){v.x,v.y}));
int mid=l+r>>1;
ins(o<<1,l,mid,v);
ins(o<<1|1,mid+1,r,v);
}
ll dot(const Node &a,const Node &b) {
return 1ll*a.x*b.x+1ll*a.y*b.y;
}
ll cross(const Node &a,const Node &b) {
return 1ll*a.x*b.y-1ll*a.y*b.x;
}
void dicon(int o,int l,int r) {
if(l==r) {
p[l]=l;
for(int i=0;i<g[o].size();++i)
ans[l]=max(ans[l],dot(q[l],g[o][i]));
return;
}
int mid=l+r>>1;
dicon(o<<1,l,mid);
dicon(o<<1|1,mid+1,r);
int L=l,R=mid+1,pc=l;
while(L<=mid or R<=r) {
if(R>r or (L<=mid and cross(q[p[L]],q[p[R]])<=0))
tmp[pc++]=p[L++];
else tmp[pc++]=p[R++];
}
for(int i=l;i<=r;++i)
p[i]=tmp[i];
tp=0;
for(int i=0;i<g[o].size();++i) {
while(tp>1 and cross(stk[tp]-stk[tp-1],g[o][i]-stk[tp-1])>=0)
--tp;
stk[++tp]=g[o][i];
}
if(tp) {
for(int i=l,j=1;i<=r;++i) {
while(j<tp and dot(stk[j],q[p[i]])<dot(stk[j+1],q[p[i]]))
++j;
ans[p[i]]=max(ans[p[i]],dot(stk[j],q[p[i]]));
}
}
}
int main() {
int op,x,y;
for(int T=read(9);T;--T) {
op=read(9),x=read(9);
if(op==1) {
y=read(9);
vec[++n]=(node){x,y,m+1,-1};
}
else if(op==2) {
vec[x].r=m;
}
else {
y=read(9);
q[++m]=(Node){x,y};
}
}
sort(vec+1,vec+n+1);
for(int i=1;i<=n;++i) {
if(vec[i].r==-1)
vec[i].r=m;
if(vec[i].l<=vec[i].r)
ins(1,1,m,vec[i]);
}
dicon(1,1,m);
for(int i=1;i<=m;++i)
print(ans[i],'\n');
return 0;
}