zoukankan      html  css  js  c++  java
  • [bzoj4311] 向量

    Description

    你要维护一个向量集合,支持以下操作:
    1.插入一个向量 ((x,y))
    2.删除插入的第 (i) 个向量
    3.查询当前集合与 ((x,y)) 点积的最大值是多少。如果当前是空集输出 (0)

    Input

    第一行输入一个整数 (n) ,表示操作个数
    接下来 (n) 行,每行先是一个整数 (t) 表示类型,如果 (t=1),输入向量((x,y)) ;如果 (t=2) ,输入 (id) 表示删除第 (id) 个向量;否则输入 ((x,y)) ,查询
    与向量 ((x,y)) 点积最大值是多少。
    保证一个向量只会被删除一次,不会删没有插入过的向量。

    Output

    对于每条 (t=3) 的询问,输出一个答案

    Sample Input

    5

    1 3 3

    1 1 4

    3 3 3

    2 1

    3 3 3

    Sample Output

    18

    15

    HINT

    (n leq 200000) (1 leq x,y leq 10^6)


    想法

    每个向量只对一定范围内的查询操作可能有贡献,于是可以线段树分治。

    具体就是将询问按时间编号为 (1~m) ,建一棵线段树。
    每个向量 (insert) 到它有贡献的区间中,注意找到完全包含在它的贡献区间的节点后打上标记就行了,不需要下放
    怎么打标记呢?就是对每个节点开一个 (vector) ,把向量扔进去就行了。

    接着我们考虑,“求集合中与((x,y)) 点积的最大值” 怎么搞。
    对于集合中的两个向量,((u1,v1) 和 (u2,v2)) ,不妨设 (u1<u2)
    若前者不如后者,即 ((u1,v1) cdot (x,y) < (u2,v2) cdot (x,y))
    打开并整理一下得出 (-frac{x}{y} < frac{v2-v1}{u2-u1})
    也就是说我们需要维护斜率递减的凸包。

    为了维护方便,我们将向量们按 (x) 坐标从小到大依次 (insert) 到线段树中,线段树的每个节点维护一个凸包。
    最终查询的时候,在线段树上从根到特定叶子的路径上每个节点维护的凸包中二分最优解,更新答案。
    每次查询复杂度 (O(log^2n)) , 总复杂度 (O(nlog^2n))


    代码

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<vector>
     
    using namespace std;
     
    int read(){
        int x=0;
        char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
        return x;
    }
     
    const int N = 200005;
    typedef long long ll;
     
    int tot,n,m;
    struct data{ int x,y,l,r; }d[N],q[N];
    bool cmp(data x,data y) { return x.x<y.x; }
     
    int root,cnt;
    int ch[N*2][2];
    vector<data> v[N*2];
    void build(int x,int l,int r){
        if(l==r) return;
        int mid=(l+r)>>1;
        build(ch[x][0]=++cnt,l,mid);
        build(ch[x][1]=++cnt,mid+1,r);
    }
    bool bigk(data a,data b,data c) { return 1ll*(b.y-a.y)*(c.x-b.x)<=1ll*(c.y-b.y)*(b.x-a.x); }
    void ins(int x,int l,int r,int L,int R,int c){
        if(l==L && r==R){ 
            while(v[x].size()>1 && bigk(v[x][v[x].size()-2],v[x][v[x].size()-1],d[c])) v[x].pop_back();
            v[x].push_back(d[c]);
            return;
        }
        int mid=(l+r)>>1;
        if(R<=mid) ins(ch[x][0],l,mid,L,R,c);
        else if(L>mid) ins(ch[x][1],mid+1,r,L,R,c);
        else{
            ins(ch[x][0],l,mid,L,mid,c);
            ins(ch[x][1],mid+1,r,mid+1,R,c);
        }
    }
    bool check(data a,data b,data c) { return 1ll*c.y*(a.y-b.y)<1ll*c.x*(b.x-a.x); }
    ll ask(int x,int l,int r,int c){
        ll ret=0;
        if(v[x].size()>=1){
            int L=0,R=v[x].size()-1,mid;
            while(L<R){
                mid=(L+R)>>1;
                if(check(v[x][mid],v[x][mid+1],q[c])) L=mid+1;
                else R=mid;
            }
            ret=1ll*q[c].x*v[x][L].x+1ll*q[c].y*v[x][L].y;
        }
         
        if(l==r) return ret;
        int mid=(l+r)>>1;
        if(c<=mid) return max(ret,ask(ch[x][0],l,mid,c));
        return max(ret,ask(ch[x][1],mid+1,r,c));
    }
     
    int main()
    {
        int Q,t,id,x,y;
        Q=read();
        while(Q--){
            t=read();
            if(t==1) {
                x=read(); y=read();
                d[++m]=(data){x,y,n+1,-1};
            }
            else if(t==2){
                id=read();
                d[id].r=n;
            }
            else {
                x=read(); y=read();
                q[++n]=(data){x,y,0,0};
            }
        }
        for(int i=1;i<=m;i++) if(d[i].r==-1) d[i].r=n;
        sort(d+1,d+1+m,cmp);
         
        build(root=++cnt,1,n);
        for(int i=1;i<=m;i++)
            if(d[i].l<=d[i].r) ins(root,1,n,d[i].l,d[i].r,i);
         
        for(int i=1;i<=n;i++) printf("%lld
    ",ask(root,1,n,i));
         
        return 0;
    } 
    
    
    既然选择了远方,便只顾风雨兼程
  • 相关阅读:
    基于thinkphp3.2.3开发的CMS内容管理系统(二)- Rbac用户权限
    phpstrom 快捷键
    基于thinkphp3.2.3开发的CMS内容管理系统
    html中的字幕滚动marquee属性
    学会这些网站优化技巧,秒变seo专家
    服务器设置防火墙规则,实现远程桌面连接的ip限制
    IIS7.5中神秘的ApplicationPoolIdentity
    mysql 安装成功后如何设置密码?
    网站优化提高加载速度的14个技巧
    解决帝国cms系统后台管理员登录密码输入五次密码错误后需等候60分钟的方法
  • 原文地址:https://www.cnblogs.com/lindalee/p/11366747.html
Copyright © 2011-2022 走看看