[BZOJ4311]向量(凸包+三分+线段树分治)
2018-11-02 17:58
375 查看
可以发现答案一定在所有向量终点形成的上凸壳上,于是在上凸壳上三分即可。
对于删除操作,相当于每个向量有一个作用区间,线段树分治即可。$O(n\log^2 n)$
同时可以发现,当询问按斜率排序后,每个凸壳上的决策点也是单调变化的,于是可以记录每次的决策位置。$O(n\log n)$
$O(n\log^2 n)$:
#include<cstdio> #include<vector> #include<cstring> #include<algorithm> #define ls (x<<1) #define rs (ls|1) #define lson ls,L,mid #define rson rs,mid+1,R #define rep(i,l,r) for (int i=(l); i<=(r); i++) typedef long long ll; using namespace std; const int N=200010; int n,op,x,y,tim,tot,d[N<<2]; struct P{ ll x,y; }; struct D{ int l,r; P p; }p ,q ; vector<P>v[N<<2]; P operator -(P a,P b){ return (P){a.x-b.x,a.y-b.y}; } ll operator *(P a,P b){ return a.x*b.y-a.y*b.x; } bool cmp1(const D &a,const D &b){ return (a.p.x==b.p.x) ? a.p.y<b.p.y : a.p.x<b.p.x; } bool cmp2(const D &a,const D &b){ return a.p*b.p<0; } ll calc(P a,P b){ return a.x*b.x+a.y*b.y; } void ins(int x,int L,int R,int l,int r,P p){ if (l<=L && R<=r){ while (v[x].size()>1 && (v[x][v[x].size()-1]-v[x][v[x].size()-2])*(p-v[x][v[x].size()-2])>=0) v[x].pop_back(); v[x].push_back(p); return; } int mid=(L+R)>>1; if (l<=mid) ins(lson,l,r,p); if (r>mid) ins(rson,l,r,p); } ll que(int x,int L,int R,int pos,P p){ ll ans=0; if (v[x].size()){ int l=0,r=v[x].size()-1; while (l+2<r){ int m1=l+(r-l)/3,m2=r-(r-l)/3; if (calc(p,v[x][m1])>calc(p,v[x][m2])) r=m2; else l=m1; } rep(i,l,r) ans=max(ans,calc(p,v[x][i])); } if (L==R) return ans; int mid=(L+R)>>1; if (pos<=mid) return max(ans,que(lson,pos,p)); else return max(ans,que(rson,pos,p)); } int main(){ freopen("bzoj4311.in","r",stdin); freopen("bzoj4311.out","w",stdout); scanf("%d",&n); rep(i,1,n){ scanf("%d",&op); if (op==1) scanf("%d%d",&x,&y),p[++tim]=(D){i,n,x,y}; if (op==2) scanf("%d",&x),p[x].r=i; if (op==3) scanf("%d%d",&x,&y),q[++tot]=(D){i,tot,x,y}; } sort(p+1,p+tim+1,cmp1); rep(i,1,tim) ins(1,1,n,p[i].l,p[i].r,p[i].p); rep(i,1,tot) printf("%lld\n",que(1,1,n,q[i].l,q[i].p)); return 0; }
$O(n\log n)$
#include<cstdio> #include<vector> #include<cstring> #include<algorithm> #define ls (x<<1) #define rs (ls|1) #define lson ls,L,mid #define rson rs,mid+1,R #define rep(i,l,r) for (int i=(l); i<=(r); i++) typedef long long ll; using namespace std; const int N=200010; ll ans ; int n,op,x,y,tim,tot,d[N<<2]; struct P{ ll x,y; }; struct D{ int l,r; P p; }p ,q ; vector<P>v[N<<2]; P operator -(P a,P b){ return (P){a.x-b.x,a.y-b.y}; } ll operator *(P a,P b){ return a.x*b.y-a.y*b.x; } bool cmp1(const D &a,const D &b){ return (a.p.x==b.p.x) ? a.p.y<b.p.y : a.p.x<b.p.x; } bool cmp2(const D &a,const D &b){ return a.p*b.p<0; } ll calc(P a,P b){ return a.x*b.x+a.y*b.y; } void ins(int x,int L,int R,int l,int r,P p){ if (l<=L && R<=r){ while (v[x].size()>1 && (v[x][v[x].size()-1]-v[x][v[x].size()-2])*(p-v[x][v[x].size()-2])>=0) v[x].pop_back(); v[x].push_back(p); return; } int mid=(L+R)>>1; if (l<=mid) ins(lson,l,r,p); if (r>mid) ins(rson,l,r,p); } ll que(int x,int L,int R,int pos,P p){ ll ans=0; if (v[x].size()){ while (d[x]<(int)v[x].size()-1 && calc(p,v[x][d[x]+1])>=calc(p,v[x][d[x]])) d[x]++; ans=calc(p,v[x][d[x]]); } if (L==R) return ans; int mid=(L+R)>>1; if (pos<=mid) return max(ans,que(lson,pos,p)); else return max(ans,que(rson,pos,p)); } int main(){ freopen("bzoj4311.in","r",stdin); freopen("bzoj4311.out","w",stdout); scanf("%d",&n); rep(i,1,n){ scanf("%d",&op); if (op==1) scanf("%d%d",&x,&y),p[++tim]=(D){i,n,x,y}; if (op==2) scanf("%d",&x),p[x].r=i; if (op==3) scanf("%d%d",&x,&y),q[++tot]=(D){i,tot,x,y}; } sort(p+1,p+tim+1,cmp1); rep(i,1,tim) ins(1,1,n,p[i].l,p[i].r,p[i].p); sort(q+1,q+tot+1,cmp2); rep(i,1,tot) ans[q[i].r]=que(1,1,n,q[i].l,q[i].p); rep(i,1,tot) printf("%lld\n",ans[i]); return 0; }
相关文章推荐
- 【bzoj4311】向量 线段树按时间分治+凸包+三分
- BZOJ 4311: 向量(线段树分治+凸包+三分)
- 【bzoj4311】向量 线段树对时间分治+STL-vector维护凸包
- 【线段树分治】[BZOJ4311]向量
- 【BZOJ】4311: 向量(线段树分治板子题)
- BZOJ_4311_向量_线段树按时间分治
- BZOJ3533 [Sdoi2014]向量集 【线段树 + 凸包 + 三分】
- BZOJ 4311: 向量( 按时间分治 + 线段树 )
- bzoj 4311 向量 时间线建线段树+凸包+三分
- BZOJ4311 向量(线段树分治+三分)
- bzoj 4311: 向量 线段树分治+凸包+三分
- BZOJ 3533: [Sdoi2014]向量集( 线段树 + 三分 )
- BZOJ 3533 [Sdoi2014]向量集(线段树套凸包)(含对拍)
- bzoj4311 向量(线段树分治+凸包)
- [BZOJ3203]-[Sdoi2013]保护出题人-凸包+三分
- [BZOJ3295][Cqoi2011]动态逆序对(树状数组套线段树||cdq分治)
- [BZOJ4059][Cerc2012]Non-boring sequences(扫描线+线段树||暴力分治)
- [BZOJ1492][NOI2007]货币兑换Cash(斜率优化dp+splay|cdq分治维护凸包)
- BZOJ 4311 向量
- bzoj2388 旅行规划(分块+凸包+三分)