• [BZOJ4311]向量(凸包+三分+线段树分治)


    可以发现答案一定在所有向量终点形成的上凸壳上,于是在上凸壳上三分即可。

    对于删除操作,相当于每个向量有一个作用区间,线段树分治即可。$O(nlog^2 n)$

    同时可以发现,当询问按斜率排序后,每个凸壳上的决策点也是单调变化的,于是可以记录每次的决策位置。$O(nlog n)$

    $O(nlog^2 n)$:

     1 #include<cstdio>
     2 #include<vector>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define ls (x<<1)
     6 #define rs (ls|1)
     7 #define lson ls,L,mid
     8 #define rson rs,mid+1,R
     9 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
    10 typedef long long ll;
    11 using namespace std;
    12 
    13 const int N=200010;
    14 int n,op,x,y,tim,tot,d[N<<2];
    15 struct P{ ll x,y; };
    16 struct D{ int l,r; P p; }p[N],q[N];
    17 vector<P>v[N<<2];
    18 P operator -(P a,P b){ return (P){a.x-b.x,a.y-b.y}; }
    19 ll operator *(P a,P b){ return a.x*b.y-a.y*b.x; }
    20 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; }
    21 bool cmp2(const D &a,const D &b){ return a.p*b.p<0; }
    22 ll calc(P a,P b){ return a.x*b.x+a.y*b.y; }
    23 
    24 void ins(int x,int L,int R,int l,int r,P p){
    25     if (l<=L && R<=r){
    26         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();
    27         v[x].push_back(p); return;
    28     }
    29     int mid=(L+R)>>1;
    30     if (l<=mid) ins(lson,l,r,p);
    31     if (r>mid) ins(rson,l,r,p);
    32 }
    33 
    34 ll que(int x,int L,int R,int pos,P p){
    35     ll ans=0;
    36     if (v[x].size()){
    37         int l=0,r=v[x].size()-1;
    38         while (l+2<r){
    39             int m1=l+(r-l)/3,m2=r-(r-l)/3;
    40             if (calc(p,v[x][m1])>calc(p,v[x][m2])) r=m2; else l=m1;
    41         }
    42         rep(i,l,r) ans=max(ans,calc(p,v[x][i]));
    43     }
    44     if (L==R) return ans;
    45     int mid=(L+R)>>1;
    46     if (pos<=mid) return max(ans,que(lson,pos,p)); else return max(ans,que(rson,pos,p));
    47 }
    48 
    49 int main(){
    50     freopen("bzoj4311.in","r",stdin);
    51     freopen("bzoj4311.out","w",stdout);
    52     scanf("%d",&n);
    53     rep(i,1,n){
    54         scanf("%d",&op);
    55         if (op==1) scanf("%d%d",&x,&y),p[++tim]=(D){i,n,x,y};
    56         if (op==2) scanf("%d",&x),p[x].r=i;
    57         if (op==3) scanf("%d%d",&x,&y),q[++tot]=(D){i,tot,x,y};
    58     }
    59     sort(p+1,p+tim+1,cmp1);
    60     rep(i,1,tim) ins(1,1,n,p[i].l,p[i].r,p[i].p);
    61     rep(i,1,tot) printf("%lld
    ",que(1,1,n,q[i].l,q[i].p));
    62     return 0;
    63 }

    $O(nlog n)$

     1 #include<cstdio>
     2 #include<vector>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define ls (x<<1)
     6 #define rs (ls|1)
     7 #define lson ls,L,mid
     8 #define rson rs,mid+1,R
     9 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
    10 typedef long long ll;
    11 using namespace std;
    12 
    13 const int N=200010;
    14 ll ans[N];
    15 int n,op,x,y,tim,tot,d[N<<2];
    16 struct P{ ll x,y; };
    17 struct D{ int l,r; P p; }p[N],q[N];
    18 vector<P>v[N<<2];
    19 P operator -(P a,P b){ return (P){a.x-b.x,a.y-b.y}; }
    20 ll operator *(P a,P b){ return a.x*b.y-a.y*b.x; }
    21 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; }
    22 bool cmp2(const D &a,const D &b){ return a.p*b.p<0; }
    23 ll calc(P a,P b){ return a.x*b.x+a.y*b.y; }
    24 
    25 void ins(int x,int L,int R,int l,int r,P p){
    26     if (l<=L && R<=r){
    27         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();
    28         v[x].push_back(p); return;
    29     }
    30     int mid=(L+R)>>1;
    31     if (l<=mid) ins(lson,l,r,p);
    32     if (r>mid) ins(rson,l,r,p);
    33 }
    34 
    35 ll que(int x,int L,int R,int pos,P p){
    36     ll ans=0;
    37     if (v[x].size()){
    38         while (d[x]<(int)v[x].size()-1 && calc(p,v[x][d[x]+1])>=calc(p,v[x][d[x]])) d[x]++;
    39         ans=calc(p,v[x][d[x]]);
    40     }
    41     if (L==R) return ans;
    42     int mid=(L+R)>>1;
    43     if (pos<=mid) return max(ans,que(lson,pos,p)); else return max(ans,que(rson,pos,p));
    44 }
    45 
    46 int main(){
    47     freopen("bzoj4311.in","r",stdin);
    48     freopen("bzoj4311.out","w",stdout);
    49     scanf("%d",&n);
    50     rep(i,1,n){
    51         scanf("%d",&op);
    52         if (op==1) scanf("%d%d",&x,&y),p[++tim]=(D){i,n,x,y};
    53         if (op==2) scanf("%d",&x),p[x].r=i;
    54         if (op==3) scanf("%d%d",&x,&y),q[++tot]=(D){i,tot,x,y};
    55     }
    56     sort(p+1,p+tim+1,cmp1);
    57     rep(i,1,tim) ins(1,1,n,p[i].l,p[i].r,p[i].p);
    58     sort(q+1,q+tot+1,cmp2);
    59     rep(i,1,tot) ans[q[i].r]=que(1,1,n,q[i].l,q[i].p);
    60     rep(i,1,tot) printf("%lld
    ",ans[i]);
    61     return 0;
    62 }
  • 相关阅读:
    mac lsof使用查看端口
    mac 安装gevent报错
    vim命令学习
    linux批量关闭进程
    坐标点转换
    screen命令记录
    hashlib模块
    PyYAML和configparser模块讲解
    xml处理模块
    json、pickleshelve模块(超级好用~!)讲解
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9897624.html
Copyright © 2020-2023  润新知