文章目录
- 题目描述
- 数据范围
- 解析
- 代码
题目描述
你要维护一个向量集合,支持以下操作:
插入一个向量 。
删除插入的第 x 个向量。
查询当前集合与(x,y)(x,y)(x,y) 点积的最大值是多少。如果当前是空集输出0。
数据范围
n<=2e5,x、y∈[1,2e6]n<=2e5,x、y∈[1,2e6]n<=2e5,x、y∈[1,2e6]
解析
考虑作当前向量的垂线,该线自上而下平移截得的第一个向量对应的点就是答案
如果本题没有删除操作,可以利用一个凸包来维护
但是如何支持删除呢?
考虑离线,对询问时间维护一个线段树
那么每个向量都有一个对应的有效区间
把该向量按照区间修改的方式加到线段树上,对每个线段树节点维护一个凸包
询问是从叶节点一直往上走,对每一个节点的凸包二分找到切点一直更新答案
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;
const int M=2e6+100;
#define ll long long
ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();};while(isdigit(c)){x=x*10+c-'0';c=getchar();};return x*f;
}
int n,m;
struct node{ll x,y;int id;bool operator < (const node o){if(x!=o.x) return x<o.x;return y<o.y;}
}p[N],ask[N];
int num,ans[N],cnt;
#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs (k<<1|1)
#define ed (tr[k].size()-1)
vector<int>tr[N<<2];
void add(int k,int x){while(tr[k].size()>1&&(p[tr[k][ed]].y-p[tr[k][ed-1]].y)*(p[x].x-p[tr[k][ed]].x)<=(p[x].y-p[tr[k][ed]].y)*(p[tr[k][ed]].x-p[tr[k][ed-1]].x)) tr[k].pop_back();tr[k].push_back(x);
}
void insert(int k,int l,int r,int x,int y,int o){//printf("insert:l=%d r=%d x=%d y=%d o=%d mid=%d %d %d\n",l,r,x,y,o,mid,x<=mid,y>mid);if(x<=l&&r<=y){//printf(" add:l=%d r=%d o=%d\n",l,r,o);add(k,o);return;}if(x<=mid) insert(ls,l,mid,x,y,o);if(y>mid) insert(rs,mid+1,r,x,y,o);
}
int find(int k,ll x,ll y){//printf(" k=%d find: siz=%d\n",k,tr[k].size());//for(int i=0;i<tr[k].size();i++) printf(" (%lld %lld)",p[tr[k][i]].x,p[tr[k][i]].y);//printf("\n");if(!tr[k].size()) return -1;else if(tr[k].size()==1||(p[tr[k][ed]].y-p[tr[k][ed-1]].y)*y>=-x*(p[tr[k][ed]].x-p[tr[k][ed-1]].x)) return tr[k][ed];int l=0,r=ed;while(l<r){int o=(l+r)>>1;if(o==ed||(p[tr[k][o+1]].y-p[tr[k][o]].y)*y<=-x*(p[tr[k][o+1]].x-p[tr[k][o]].x)) r=o;else l=o+1;//printf(" o=%d l=%d r=%d\n",o,l,r);}return tr[k][l];
}
ll query(int k,int l,int r,int o,ll x,ll y){//printf("k=%d l=%d r=%d x=%lld y=%lld\n",k,l,r,x,y);int pl=find(k,x,y);ll res=pl==-1?0:x*p[pl].x+y*p[pl].y;if(l==r) return res;if(o<=mid) res=max(res,query(ls,l,mid,o,x,y));else res=max(res,query(rs,mid+1,r,o,x,y));return res;
}
int st[N],eed[N];
int main(){n=read();
// for(int i=1;i<=100;i++) tr[i].resize(10);for(int i=1;i<=n;i++){int f=read();if(f==1){int x=read(),y=read();//printf("%d %d %d\n",f,x,y);p[++cnt]=(node){x,y,cnt};st[cnt]=i;eed[cnt]=n;}else if(f==2){int x=read();eed[x]=i-1;//printf("%d %d\n",f,x);}else{int x=read(),y=read();//printf("%d %d %d\n",f,x,y);ask[++num]=(node){x,y,i};}}sort(p+1,p+1+cnt);for(int i=1;i<=cnt;i++){//printf("i=%d l=%d r=%d\n",i,st[p[i].id],eed[p[i].id]);insert(1,1,n,st[p[i].id],eed[p[i].id],i);}for(int i=1;i<=num;i++){printf("%lld\n",query(1,1,n,ask[i].id,ask[i].x,ask[i].y));}return 0;
}
/*
5
3 84040 650026
3 702678 199950
1 826333 497249
1 133580 956915
3 36119 655069
*/