bzoj4311向量(线段树分治+斜率优化)
Posted hfctf0210
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4311向量(线段树分治+斜率优化)相关的知识,希望对你有一定的参考价值。
第二道线段树分治。
首先设当前向量是(x,y),剩余有两个不同的向量(u1,v1)(u2,v2),假设u1>u2,则移项可得,若(u1,v1)优于(u2,v2),则-x/y>(v1-v2)/(u1-u2),然后维护上凸壳后进行三分即可,复杂度O(nlog2n),如果将询问排序扫一遍,可以优化到O(nlogn),当然我没写。
#include<bits/stdc++.h> #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 using namespace std; typedef long long ll; const int N=2e5+7; struct nodeint x,y,l,r;p[N],q[N]; int n,tim,tot,top; ll ans[N]; vector<node>a[N<<2]; node st[N]; bool cmp(node a,node b)return a.x==b.x?a.y<b.y:a.x<b.x; ll dot(node a,node b)return 1ll*a.x*b.x+1ll*a.y*b.y; ll cross(node a,node b,node c)return 1ll*(a.x-c.x)*(b.y-c.y)-1ll*(a.y-c.y)*(b.x-c.x); void update(int L,int R,int id,int l,int r,int rt) if(L<=l&&r<=R)a[rt].push_back(p[id]);return; int mid=l+r>>1; if(L<=mid)update(L,R,id,lson); if(R>mid)update(L,R,id,rson); ll query(int id) int l=1,r=top,m1,m2; ll ret=0; while(r-l>=3) m1=l+(r-l)/3,m2=r-(r-l)/3; if(dot(q[id],st[m1])<=dot(q[id],st[m2]))l=m1;else r=m2; for(int i=l;i<=r;i++)ret=max(ret,dot(q[id],st[i])); return ret; void work(int x,int l,int r) if(!a[x].size())return; top=0; sort(a[x].begin(),a[x].end(),cmp); for(int i=0;i<a[x].size();i++) while(top>1&&cross(st[top-1],st[top],a[x][i])>=0)top--; st[++top]=a[x][i]; for(int i=l;i<=r;i++)ans[i]=max(ans[i],query(i)); void divide(int l,int r,int rt) work(rt,l,r); if(l==r)return; int mid=l+r>>1;divide(lson),divide(rson); int main() scanf("%d",&n); for(int i=1,op,x,y;i<=n;i++) scanf("%d%d",&op,&x); if(op==1)scanf("%d",&y),p[++tot]=(node)x,y,tim+1,-1; else if(op==2)p[x].r=tim; else scanf("%d",&y),q[++tim]=(node)x,y,tim,tim; for(int i=1;i<=tot;i++)if(p[i].r==-1)p[i].r=tim; for(int i=1;i<=tot;i++)if(p[i].l<=p[i].r)update(p[i].l,p[i].r,i,1,tim,1); divide(1,tim,1); for(int i=1;i<=tim;i++)printf("%lld\n",ans[i]);
以上是关于bzoj4311向量(线段树分治+斜率优化)的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ3533 [Sdoi2014]向量集 线段树 + 凸包 + 三分
BZOJ-1492货币兑换Cash DP + 斜率优化 + CDQ分治