zoukankan      html  css  js  c++  java
  • bzoj3533: [Sdoi2014]向量集

    Description

    维护一个向量集合,在线支持以下操作:
    "A x y (|x|,|y| < =10^8)":加入向量(x,y);
    " Q x y l r (|x|,|y| < =10^8,1 < =L < =R < =T,其中T为已经加入的向量个数)询问第L个到第R个加入的向量与向量(x,y)的点积的最大值。
        集合初始时为空。

    Input

        输入的第一行包含整数N和字符s,分别表示操作数和数据类别;
        接下来N行,每行一个操作,格式如上所述。
        请注意s≠'E'时,输入中的所有整数都经过了加密。你可以使用以下程序
    得到原始输入:
    inline int decode (int x long long lastans) {
         return x ^ (lastans & Ox7fffffff);
    }
    function decode
    begin
        其中x为程序读入的数,lastans为之前最后一次询问的答案。在第一次询问之前,lastans=0。

    注:向量(x,y)和(z,W)的点积定义为xz+yw。

    Output

      对每个Q操作,输出一个整数表示答案。

    将向量看作平面上的点,线段树维护上、下凸包,在凸包上三分可得到最优解。对线段树的每个区间,当区间内向量都已读入时计算凸包。
    #include<cstdio>
    #include<algorithm>
    typedef long long i64;
    char buf[5000000],*ptr=buf,*pmx=buf+5000000;
    const i64 inf=1ll<<62;
    const int N=1e7;
    int g(){
        if(ptr==pmx)fread(ptr=buf,1,5000000,stdin);
        return *ptr++;
    }
    int _(){
        int x=0,f=1,c=g();
        while(c<48||c>57)c=='-'&&(f=-1),c=g();
        while(c>47&&c<58)x=x*10+c-48,c=g();
        return x*f;
    }
    int _c(){
        int c=g();
        while(c<'A'||c>'Z')c=g();
        return c;
    }
    void maxs(i64&a,i64 b){if(a<b)a=b;}
    void maxs(int&a,int b){if(a<b)a=b;}
    void mins(int&a,int b){if(a>b)a=b;}
    struct pos{
        int x,y;
        i64 operator()(pos a){
            return i64(x)*a.x+i64(y)*a.y;
        }
    }mem[21000007],*mp=mem;
    pos operator-(pos a,pos b){
        return (pos){a.x-b.x,a.y-b.y};
    }
    i64 operator*(pos a,pos b){
        return i64(a.x)*b.y-i64(a.y)*b.x;
    }
    bool operator<(pos a,pos b){
        return a.x!=b.x?a.x<b.x:a.y<b.y;
    }
    struct node{
        pos*l,*r;
        void init(int x,int y){
            l=mp;
            *mp++=(pos){x,y};
            r=mp;
        }
        void ins(pos x){
            if(mp>l&&mp[-1].x==x.x)--mp;
            while(mp-l>=2&&(x-mp[-1])*(mp[-2]-mp[-1])>=0)--mp;
            *mp++=x;
        }
        void init(node a,node b){
            if(!a.l)*this=b;
            else if(!b.l)*this=a;
            else{
                l=mp;
                pos*ap=a.l,*bp=b.l;
                while(ap!=a.r&&bp!=b.r){
                    if(*ap<*bp)ins(*ap++);
                    else ins(*bp++);
                }
                while(ap!=a.r)ins(*ap++);
                while(bp!=b.r)ins(*bp++);
                r=mp;
            }
        }
        i64 find(pos x){
            if(!l)return -1ll<<62;
            i64 v1,v2;
            int L=0,R=r-l-1,M1,M2;
            while(R-L>3){
                M1=L+R>>1;
                M2=M1+1;
                if(x(l[M1])<x(l[M2]))L=M1;
                else R=M2;
            }
            for(v1=x(l[L++]);L<=R;++L)maxs(v1,x(l[L]));
            return v1;
        }
    }us[1051111],ds[1051111];
    bool d[1051111];
    int n,de,la=0,x,y,l,r,id=0;
    int main(){
        n=_();de=_c()!='E';
        for(int i=0;i<n;++i){
            if(_c()=='A'){
                x=_();y=_();++id;
                if(de)x^=la,y^=la;
                int w=id+524288;
                us[w].init(x,y);
                ds[w].init(x,-y);
                d[w]=1;
                for(w>>=1;w&&d[w<<1^1];w>>=1){
                    us[w].init(us[w<<1],us[w<<1^1]);
                    ds[w].init(ds[w<<1],ds[w<<1^1]);
                    d[w]=1;d[w<<1^1]=0;
                }
            }else{
                x=_();y=_();l=_();r=_();
                if(de)x^=la,y^=la,l^=la,r^=la;
                i64 ans=-1ll<<62;
                pos p1=(pos){x,y},p2=(pos){x,-y};
                for(l+=524287,r+=524289;l^r^1;l>>=1,r>>=1){
                    if(~l&1)maxs(ans,us[l^1].find(p1)),maxs(ans,ds[l^1].find(p2));
                    if(r&1)maxs(ans,us[r^1].find(p1)),maxs(ans,ds[r^1].find(p2));
                }
                printf("%lld
    ",ans);
                la=ans&0x7fffffff;
            }
        }
        return 0;
    }
  • 相关阅读:
    luogu4365 秘密袭击 (生成函数+线段树合并+拉格朗日插值)
    [模板]左偏树
    luogu4166 最大土地面积 (旋转卡壳)
    bzoj3168 钙铁锌硒维生素 (矩阵求逆+二分图最小字典序匹配)
    [模板]矩阵树定理
    [模板]快速傅里叶变换(FFT)
    [模板]Min_25筛
    [模板]杜教筛
    [模板]莫比乌斯反演
    DrawerLayout—侧拉栏的使用
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6146834.html
Copyright © 2011-2022 走看看