zoukankan      html  css  js  c++  java
  • 51Nod1502 苹果曼和纸

    题目点这里

    漏写博客好多天了,赶快来补

    这道题是一个裸的模拟题,注意到纸片总长度不会增加,所以用一个带翻转的splay来维护一下

    每次将前半段翻转和后一段做加法合并就好了,均摊logn

    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 100010
    #define son(x) (s[f[x]][1]==x)
    using namespace std;
    int f[N],s[N][2],sz[N],v[N],t[N];
    int n,m,cnt=0,rt=0,tp=0,stk[N],r[N];
    inline int newnode(int p){
        ++cnt; sz[cnt]=1;
        t[cnt]=v[cnt]=p;
        return cnt;
    }
    inline int ps(int x){
        sz[x]=sz[s[x][0]]+sz[s[x][1]]+1;
        t[x]=t[s[x][0]]+v[x]+t[s[x][1]]; 
    }
    inline void reverse(int x){
        swap(s[x][0],s[x][1]);
        r[s[x][0]]^=1; r[s[x][1]]^=1; r[x]=0;
    }
    inline void rot(int x){
        int p=f[x],g=f[p],d=son(x);
        s[p][d]=s[x][!d]; f[s[p][d]]=p;
        s[x][!d]=p; f[p]=x; f[x]=g;
        if(g) s[g][p==s[g][1]]=x; ps(p); ps(x);
    }
    inline void splay(int x,int rt=0){
        for(int y=x;y;y=f[y]) stk[++tp]=y;
        for(;tp;--tp) if(r[stk[tp]]) reverse(stk[tp]);
        for(int p;(p=f[x])!=rt;rot(x))
            if(f[p]!=rt && son(x)==son(p)) rot(p);
        if(!rt) ::rt=x;
    }
    inline int select(int x,int k){
        for(int w;;){
            if(r[x]) reverse(x);
            w=sz[s[x][0]]+1;
            if(w==k) return x;
            if(k<w) x=s[x][0];
            else k-=w,x=s[x][1];
        }
    }
    inline int rank(int x){
        int r=sz[s[x][0]]+1;
        for(;x;x=f[x])
            if(son(x)) r+=sz[s[f[x]][0]]+1;
        return r;
    }
    inline int merge(int x,int y){
        if(sz[x]>sz[y]) swap(x,y);
        for(int i=1;sz[x];++i){
            splay(x=select(x,1));
            splay(y=select(y,i));
            v[y]+=v[x]; ps(y); x=s[x][1];
        }
        return y;
    }
    void print(int x){
        if(!x) return;
        print(s[x][0]);
        printf("[%d]",v[x]);
        print(s[x][1]);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int x,i=1;i<=n;++i){
            x=newnode(1);
            if(i-1) f[i-1]=x,s[x][0]=i-1,ps(x);
        }
        rt=cnt; int t1=newnode(0),t2=newnode(0); f[t1]=t2; s[t2][0]=t1;
        for(int o,x,y;m--;){
            scanf("%d%d",&o,&x);
            if(o==1){
                splay(x=select(rt,x));
                y=s[x][1]; s[x][1]=0; f[y]=0; ps(x); r[x]=1;
                rt=merge(x,y);
            } else {
                scanf("%d",&y);    
                s[t1][1]=rt; f[rt]=t1; ps(t1); ps(t2);
                splay(select(t2,++x));
                splay(select(rt,y+2),rt);
                printf("%d
    ",t[s[s[rt][1]][0]]);
                splay(t2); splay(t1,rt); f[rt=s[t1][1]]=0; s[t1][1]=0;
            }
            //print(rt); puts("");
        }
    }

  • 相关阅读:
    1.C和C++区别,以及const分析(底层const/顶层const)
    4.移植驱动到3.4内核-移植总结
    3.移植驱动到3.4内核-移植DM9000C驱动
    2.移植3.4内核-支持烧写yaffs2,裁剪内核并制作补丁
    Android Support v4、v7、v13、v14、v17的区别和应用场景
    Android利用canvas画各种图形
    ActionBar 自定义布局定义
    android动画坐标定义
    GitHub上最著名的Android播放器开源项目大全
    CardView 简介和使用
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477117.html
Copyright © 2011-2022 走看看