【bzoj4311】向量 线段树按时间分治+凸包+三分

来源:互联网 发布:剑灵人族男身材数据 编辑:程序博客网 时间:2024/05/12 01:39

好像没什么好说的,记录每个点进出的时刻,每个点对应线段树上的O(logn)个节点,然后按时间分治就可以了。


#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<iostream>#include<vector>#define maxn 200010 using namespace std;struct yts1{long long x,y;}p[maxn],st[maxn],tmp[maxn];struct yts{int l,r;vector<yts1> v;}t[4*maxn];struct yts2{long long x,y,ans;}q[maxn];int n,m,L[maxn],tot,top;long long operator^ (yts1 a,yts1 b){return a.x*b.y-a.y*b.x;}long long operator* (yts1 a,yts1 b){return a.x*b.x+a.y*b.y;}bool operator< (yts1 a,yts1 b){return a.x<b.x || (a.x==b.x && a.y<b.y);}yts1 operator-(yts1 a,yts1 b){yts1 ans;ans.x=a.x-b.x;ans.y=a.y-b.y;return ans;}void build(int i,int l,int r){t[i].l=l;t[i].r=r;if (l==r) return;int mid=(l+r)/2;build(i*2,l,mid);build(i*2+1,mid+1,r);}void insert(int i,int l,int r,int x){if (l<=t[i].l && t[i].r<=r){t[i].v.push_back(p[x]);return;}int mid=(t[i].l+t[i].r)/2;if (l<=mid) insert(i*2,l,r,x);if (mid<r) insert(i*2+1,l,r,x);}void query(int i){if (!top) return;yts1 o;o.x=q[i].x;o.y=q[i].y;int l=1,r=top;while (r-l>=3){int mid=l+(r-l)/3,midmid=r-(r-l)/3;if ((o*st[mid])>(o*st[midmid])) r=midmid; else l=mid;}for (int j=l;j<=r;j++) q[i].ans=max(q[i].ans,o*st[j]);}void solve(int x,int l,int r){int mid=(l+r)/2;if (l<r) solve(x*2,l,mid),solve(x*2+1,mid+1,r);top=0;sort(t[x].v.begin(),t[x].v.end());for (int i=0;i<t[x].v.size();i++){while (top>1 && ((t[x].v[i]-st[top])^(st[top]-st[top-1]))<=0) top--;st[++top]=t[x].v[i];}for (int i=l;i<=r;i++)  if (q[i].x) query(i);}int main(){scanf("%d",&n);build(1,1,n);for (int i=1;i<=n;i++){int opt;long long x,y;scanf("%d",&opt);if (opt==1) {scanf("%lld%lld",&x,&y);p[++tot].x=x,p[tot].y=y,L[tot]=i;}if (opt==2) {scanf("%lld",&x);insert(1,L[x],i,x);L[x]=0;}if (opt==3) scanf("%lld%lld",&q[i].x,&q[i].y);}for (int i=1;i<=tot;i++) if (L[i]) insert(1,L[i],n,i);solve(1,1,n);for (int i=1;i<=n;i++)  if (q[i].x) printf("%lld\n",q[i].ans);return 0;}



0 0
原创粉丝点击