zoukankan      html  css  js  c++  java
  • BZOJ 3595: [Scoi2014]方伯伯的Oj Splay + 动态裂点 + 卡常

    Description

    方伯伯正在做他的Oj。现在他在处理Oj上的用户排名问题。
    Oj上注册了n个用户,编号为1~”,一开始他们按照编号排名。方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号:
    1.操作格式为1 x y,意味着将编号为z的用户编号改为V,而排名不变,执行完该操作后需要输出该用户在队列中的位置,数据保证x必然出现在队列中,同时1,是一个当前不在排名中的编号。
    2.操作格式为2 x,意味着将编号为x的用户的排名提升到第一位,执行完该操作后需要输出执行该操作前编号为z用户的排名。
    3.操作格式为3 x,意味着将编号为z的用户的排名降到最后一位,执行完该操作后需要输出执行该操作前编号为z用户的排名。
    4.操作格式为4 k,意味着查询当前排名为足的用户编号,执行完该操作后需要输出当前操作用户的编号。
    但同时为了防止别人监听自己的工作,方伯伯对他的操作进行了加密,即将四种操作的格式分别改为了:
    1 x+a y+a
    2 x+a
    3 x+a
    4 k+a
    其中a为上一次操作得到的输出,一开始a=0。
    例如:
    上一次操作得到的输出是5
    这一次操作的输入为:1  13 15
    因为这个输入是经过加密后的,所以你应该处理的操作是1 8 10
    现在你截获丁方伯伯的所有操作,希望你能给出结果。

    Input

    输入的第1行包含2个用空格分隔的整数n和m,表示初始用户数和操作数。
    此后有m行,每行是一个询问,询问格式如上所示。

    Output

    输出包含m行。每行包含一个整数,其中第i行的整数表示第i个操作的输出。

    和 NOIP2017 day2t3 挺像的.
     凭借自己力量独立码出这道题还是超级开心的
     假如说数据范围较小,我们可以对每一个用户开一个点,并用平衡树来维护.
     不过,此题中人数会达到 $10^8$ 级别,这样无论是空间还是时间都承受不了.
     好在操作数 $m$ 最大只有 $10^5$ 级别.
     这意味着其实有许多人之间的相对位置关系是始终不变的(操作数太少)
     我们考虑用动态裂点的方式来维护.
     相比于原来是一个点维护一个人,现在是用一个点维护连续的一排人.
     如果操作的人在一个大的点中,直接分情况讨论将该点裂成 3(或2)个新点即可.
     以上操作可以用 $splay$ 来维护.
     还有一个小小的问题,我们如何知道用户 $x$ 在 $splay$ 中所在点的编号为多少 ?
     由于点和点表示的连续区间是不可能有交集的,我们直接用一个 $set$ 来维护每一个节点的左,右端点与节点编号.
     这样,当我们想知道节点编号时直接在 $set$ 中调用 $lowerbound$ 函数来查即可.
     说起来简单,写起来细节还是挺多的.

    普通版:     

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define maxn 200004  
    #define lson(x) ch[x][0]
    #define rson(x) ch[x][1] 
    #define get(x) (ch[f[x]][1]==x) 
    using namespace std;
    inline void setIO(string s)
    {
        string in=s+".in",out=s+".out"; 
        freopen(in.c_str(),"r",stdin); 
        freopen(out.c_str(),"w",stdout); 
    }
    int n,Q,lastans,root;  
    int ch[maxn][2], f[maxn], L[maxn], R[maxn], siz[maxn], sta[maxn]; 
    inline int de()
    {
        int x; 
        scanf("%d",&x); 
        return x - lastans; 
    }
    // 右端点从小 -> 大    
    struct Node
    {
        int l,r,id;  
        Node(int l=0,int r=0,int id=0):l(l),r(r),id(id){} 
        bool operator<(Node b)const { return b.r > r; } 
    }; 
    set<Node>S; 
    set<Node>::iterator it;  
    struct Splay
    { 
        int cnt; 
        inline void init() 
        { 
            cnt=0; 
            for(int i=1;i<maxn-100;++i) sta[++cnt]=i;  
        }
        inline int newnode() 
        { 
            return sta[cnt--];  
        }
        // 内存回收   
        inline void erase(int x) 
        {
            ch[x][0]=ch[x][1]=f[x]=L[x]=R[x]=siz[x]=0; 
            sta[++cnt]=x;       
        }
        inline void pushup(int x)
        {
            siz[x]=siz[lson(x)] + siz[rson(x)] + R[x]-L[x]+1; 
        }     
        inline void rotate(int x)
        {
            int old=f[x],fold=f[old],which=get(x); 
            ch[old][which]=ch[x][which^1], f[ch[old][which]]=old; 
            ch[x][which^1]=old, f[old]=x, f[x]=fold; 
            if(fold) ch[fold][ch[fold][1]==old]=x; 
            pushup(old), pushup(x);     
        }
        // u -> x      
        inline void splay(int x,int &u)
        {
            int a=f[u]; 
            for(int fa;(fa=f[x])!=a;rotate(x)) 
            {     
                if(f[fa]!=a) 
                    rotate(get(fa)==get(x)?fa:x);             
            }
            u = x;   
        }
        // 查找第 k 大编号
        inline int find(int kth)
        {
            int p = root;    
            while(1)
            {
                if(siz[lson(p)] >= kth) p=ch[p][0]; 
                else 
                {
                    kth-=(siz[lson(p)]); 
                    if(kth > R[p] - L[p] + 1) kth -= (R[p] - L[p] + 1), p = rson(p); 
                    else 
                    {
                        return L[p] + kth - 1; 
                    }
                }
            } 
        }  
        inline void del(int x)
        {
            int p=x; 
            // root = x 
            splay(x,root); 
            if(!ch[x][0] && !ch[x][1]) root = 0;  
            else if(!ch[x][0])  root = ch[x][1], f[ch[x][1]]=0; 
            else if(!ch[x][1]) root = ch[x][0], f[ch[x][0]]=0;      
            else 
            { 
                p = ch[x][0]; 
                while(rson(p)) p = rson(p); 
                splay(p, ch[x][0]);    
                rson(p) = ch[x][1], f[ch[x][1]] = p, f[p] = 0; 
                pushup(p);     
                root=p;   
            }
            S.erase(Node(L[x], R[x],x)); 
            erase(x); 
        }    
        // 第 kth 大位置之后进行插入.    
        inline int insert(int kth,int l,int r)
        {
            if(!root)
            {
                root=newnode(), L[root]=l,R[root]=r;      
                pushup(root);  
                S.insert(Node(L[root], R[root], root)); 
                return root; 
            }
            int p=root, fa=0, cur=0, tmp=0; 
            while(p) 
            {
                fa=p; 
                if(kth >= (tmp=siz[lson(p)] + R[p]-L[p]+1)) kth -= tmp, p=rson(p), cur=1; 
                else p=lson(p), cur=0;  
            }
            p = newnode(); 
            L[p]=l,R[p]=r; 
            ch[fa][cur]=p,f[p]=fa; 
            pushup(p); 
            splay(p, root);
            S.insert(Node(L[p], R[p], p));                
            return p;        
        }
        // 对于点 x, 割裂出 l 
        inline int split(int x,int l)
        {
            splay(x, root);     
            int tmp = siz[lson(x)],l1=L[x], r1=R[x], oo=0;  
            // 该点已经单独存在,无需删除     
            if(l==l1&&l==r1) return x;      
            if(l==l1) 
            {  
                del(x);    
                oo = insert(tmp,l,l); 
                insert(tmp+1,l+1,r1); 
            }
            else if(l==r1)
            {
                del(x);          
                insert(tmp,l1,r1-1); 
                oo = insert(tmp+r1-l1,r1,r1); 
            }
            else 
            { 
                del(x);   
                // printf("---------
    ");
                insert(tmp,l1,l-1);  // printf("%d %d
    ",l1,l-1); 
                oo = insert(tmp+l-l1,l,l);  // printf("%d %d
    ",l,l); 
                insert(tmp+l-l1+1,l+1,r1);  //printf("%d %d
    ",l+1,r1); 
                // for(it=S.begin();it!=S.end();it++) printf("%d %d
    ",(*it).l,(*it).r); 
            }   
            return oo; 
        }
    }tr; 
    int main()
    {
        // setIO("input"); 
        scanf("%d%d",&n,&Q);
        tr.init(); 
        tr.insert(0,1,n);     
        S.insert(Node(1,n,root));     
        while(Q--)
        {
            int opt; 
            scanf("%d",&opt); 
            if(opt==1)
            {
                // x -> y 
                int x=de(),y=de(),z;  
                it=S.lower_bound(Node(0, x, 0));         
                z = tr.split((*it).id, x);          
                S.erase(Node(L[z], R[z], z)); 
                S.insert(Node(y,y,z));                       
                tr.splay(z, root), L[z]=R[z]=y, tr.pushup(z), printf("%d
    ",lastans=siz[lson(z)]+1);  
            }
            if(opt==2)
            { 
                int x=de(), z, l, r; 
                it=S.lower_bound(Node(0, x, 0));   
                z = tr.split((*it).id, x);      
                tr.splay(z, root), printf("%d
    ",lastans=siz[lson(z)]+1); 
                l = L[z], r=R[z];     
                tr.del(z), tr.insert(0, l, r);      
            }
            if(opt==3)
            {
                int x=de(), z, l, r, kk;   
                // for(it=S.begin();it!=S.end();it++) printf("%d %d::
    ",(*it).l,(*it).r); 
                it = S.lower_bound(Node(0, x, 0));        
                z = tr.split((*it).id, x); 
                tr.splay(z, root), printf("%d
    ",lastans=siz[lson(z)]+1); 
                l = L[z], r = R[z]; 
                tr.del(z); 
                tr.insert(siz[root], l, r);      
            }
            if(opt==4)
            {
                int k=de(); 
                printf("%d
    ",lastans=tr.find(k)); 
            }
        }
        return 0; 
    }
    

      

    卡常版

    #include<bits/stdc++.h>
    #define maxn 200004  
    #define lson(x) ch[x][0]
    #define rson(x) ch[x][1] 
    #define get(x) (ch[f[x]][1]==x) 
    #define rg register
    #define O2 __attribute__((optimize("-O2")))
    using namespace std;
    char *p1,*p2,buf[100000];
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
    O2 inline void setIO(rg string s)
    {
        string in=s+".in",out=s+".out"; 
        freopen(in.c_str(),"r",stdin); 
        freopen(out.c_str(),"w",stdout); 
    }
    int n,Q,lastans,root;  
    int ch[maxn][2], f[maxn], L[maxn], R[maxn], siz[maxn], sta[maxn]; 
    O2 inline int de()
    {
        rg int x=rd(); 
        return x - lastans; 
    }
    // 右端点从小 -> 大    
    struct Node
    {
        int l,r,id;  
        Node(rg int l=0,rg int r=0,rg int id=0):l(l),r(r),id(id){} 
        bool operator<(Node b)const { return b.r > r; } 
    }; 
    set<Node>S; 
    set<Node>::iterator it;  
    struct Splay
    { 
        int cnt; 
        O2 inline void init() 
        { 
            cnt=0; 
            for(rg int i=1;i<maxn-100;++i) sta[++cnt]=i;  
        }
        O2 inline int newnode() 
        { 
            return sta[cnt--];  
        }
        // 内存回收   
        O2 inline void erase(int x) 
        {
            ch[x][0]=ch[x][1]=f[x]=L[x]=R[x]=siz[x]=0; 
            sta[++cnt]=x;       
        }
        O2 inline void pushup(int x)
        {
            siz[x]=siz[lson(x)] + siz[rson(x)] + R[x]-L[x]+1; 
        }     
        O2 inline void rotate(int x)
        {
            rg int old=f[x],fold=f[old],which=get(x); 
            ch[old][which]=ch[x][which^1], f[ch[old][which]]=old; 
            ch[x][which^1]=old, f[old]=x, f[x]=fold; 
            if(fold) ch[fold][ch[fold][1]==old]=x; 
            pushup(old), pushup(x);     
        }
        // u -> x      
        O2 inline void splay(int x,int &u)
        {
            rg int a=f[u]; 
            for(rg int fa;(fa=f[x])!=a;rotate(x)) 
            {     
                if(f[fa]!=a) 
                    rotate(get(fa)==get(x)?fa:x);             
            }
            u = x;   
        }
        // 查找第 k 大编号
        O2 inline int find(int kth)
        {
            rg int p = root;    
            while(1)
            {
                if(siz[lson(p)] >= kth) p=ch[p][0]; 
                else 
                {
                    kth-=(siz[lson(p)]); 
                    if(kth > R[p] - L[p] + 1) kth -= (R[p] - L[p] + 1), p = rson(p); 
                    else 
                    {
                        return L[p] + kth - 1; 
                    }
                }
            } 
        }  
        O2 inline void del(int x)
        {
            rg int p=x; 
            // root = x 
            splay(x,root); 
            if(!ch[x][0] && !ch[x][1]) root = 0;  
            else if(!ch[x][0])  root = ch[x][1], f[ch[x][1]]=0; 
            else if(!ch[x][1]) root = ch[x][0], f[ch[x][0]]=0;      
            else 
            { 
                p = ch[x][0]; 
                while(rson(p)) p = rson(p); 
                splay(p, ch[x][0]);    
                rson(p) = ch[x][1], f[ch[x][1]] = p, f[p] = 0; 
                pushup(p);     
                root=p;   
            }
            S.erase(Node(L[x], R[x],x)); 
            erase(x); 
        }    
        // 第 kth 大位置之后进行插入.    
        O2 inline int insert(rg int kth,rg int l,rg int r)
        {
            if(!root)
            {
                root=newnode(), L[root]=l,R[root]=r;      
                pushup(root);  
                S.insert(Node(L[root], R[root], root)); 
                return root; 
            }
            rg int p=root, fa=0, cur=0, tmp=0; 
            while(p) 
            {
                fa=p; 
                if(kth >= (tmp=siz[lson(p)] + R[p]-L[p]+1)) kth -= tmp, p=rson(p), cur=1; 
                else p=lson(p), cur=0;  
            }
            p = newnode(); 
            L[p]=l,R[p]=r; 
            ch[fa][cur]=p,f[p]=fa; 
            pushup(p); 
            splay(p, root);
            S.insert(Node(L[p], R[p], p));                
            return p;        
        }
        // 对于点 x, 割裂出 l 
        O2 inline int split(rg int x,rg int l)
        {
            splay(x, root);     
            rg int tmp = siz[lson(x)],l1=L[x], r1=R[x], oo=0;  
            // 该点已经单独存在,无需删除     
            if(l==l1&&l==r1) return x;      
            if(l==l1) 
            {  
                del(x);    
                oo = insert(tmp,l,l); 
                insert(tmp+1,l+1,r1); 
            }
            else if(l==r1)
            {
                del(x);          
                insert(tmp,l1,r1-1); 
                oo = insert(tmp+r1-l1,r1,r1); 
            }
            else 
            { 
                del(x);   
                // printf("---------
    ");
                insert(tmp,l1,l-1);  // printf("%d %d
    ",l1,l-1); 
                oo = insert(tmp+l-l1,l,l);  // printf("%d %d
    ",l,l); 
                insert(tmp+l-l1+1,l+1,r1);  //printf("%d %d
    ",l+1,r1); 
                // for(it=S.begin();it!=S.end();it++) printf("%d %d
    ",(*it).l,(*it).r); 
            }   
            return oo; 
        }
    }tr; 
    O2 int main()
    {  
        n=rd(),Q=rd();
        tr.init(); 
        tr.insert(0,1,n);     
        S.insert(Node(1,n,root));     
        while(Q--)
        {
            rg int opt=rd(); 
            if(opt==1)
            {
                // x -> y 
                rg int x=de(),y=de(),z;  
                it=S.lower_bound(Node(0, x, 0));         
                z = tr.split((*it).id, x);          
                S.erase(Node(L[z], R[z], z)); 
                S.insert(Node(y,y,z));                       
                tr.splay(z, root), L[z]=R[z]=y, tr.pushup(z), printf("%d
    ",lastans=siz[lson(z)]+1);  
            }
            if(opt==2)
            { 
                rg int x=de(), z, l, r; 
                it=S.lower_bound(Node(0, x, 0));   
                z = tr.split((*it).id, x);      
                tr.splay(z, root), printf("%d
    ",lastans=siz[lson(z)]+1); 
                l = L[z], r=R[z];     
                tr.del(z), tr.insert(0, l, r);      
            }
            if(opt==3)
            {
                rg int x=de(), z, l, r, kk;      
                it = S.lower_bound(Node(0, x, 0));        
                z = tr.split((*it).id, x); 
                tr.splay(z, root), printf("%d
    ",lastans=siz[lson(z)]+1); 
                l = L[z], r = R[z]; 
                tr.del(z); 
                tr.insert(siz[root], l, r);      
            }
            if(opt==4)
            {
                rg int k=de(); 
                printf("%d
    ",lastans=tr.find(k)); 
            }
        }
        return 0; 
    }
    

      

  • 相关阅读:
    elastic job 动态设置定时任务
    org.springframework.beans.factory.NoSuchBeanDefinitionException
    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-dependency-plugin:2.8:unpack (unpack) on project sq-integral-web: Unable to find artifact.
    The method setItems(String) in the type ForTokensTag is not applicable for the arguments (Object)
    linux 配置文件(启动文件、环境文件)启动顺序
    linux shell 执行命令顺序
    在Linux上编译使用tcmalloc
    eclipse启动报错: No Java virtual machine
    http2.0可行性研究
    python 内存问题(glibc库的malloc相关)
  • 原文地址:https://www.cnblogs.com/guangheli/p/11082657.html
Copyright © 2011-2022 走看看