题目

传送门

解法

假设向量 \((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;
}
posted on 2021-08-29 22:10  Oxide  阅读(40)  评论(0编辑  收藏  举报