zoukankan      html  css  js  c++  java
  • 1743 反转卡片

    1743 反转卡片

     

     时间限制: 2 s
     空间限制: 256000 KB
     题目等级 : 大师 Master
     
     
     
    题目描述 Description

    【dzy493941464|yywyzdzr原创】 

    小A将N张卡片整齐地排成一排,其中每张卡片上写了1~N的一个整数,每张卡片上的数各不相同。

    比如下图是N=5的一种情况:3 4 2 1 5

    接下来你需要按小A的要求反转卡片,使得左数第一张卡片上的数字是1。操作方法:令左数第一张卡片上的数是K,如果K=1则停止操作,否则将左数第1~K张卡片反转。

    第一次(K=3)反转后得到:2 4 3 1 5

    第二次(K=2)反转后得到:4 2 3 1 5

    第三次(K=4)反转后得到:1 3 2 4 5

    可见反转3次后,左数第一张卡片上的数变成了1,操作停止。

    你的任务是,对于一种排列情况,计算要反转的次数。你可以假设小A不会让你操作超过100000次。

    输入描述 Input Description

    第1行一个整数N

    第2行N个整数,为1~N的一个全排列。

    输出描述 Output Description

    仅1行,输出一个整数表示要操作的次数。

    如果经过有限次操作仍无法满足要求,输出-1。

    样例输入 Sample Input

    5

    3 4 2 1 5

    样例输出 Sample Output

    3

    数据范围及提示 Data Size & Hint

    0<N≤300,000。

    分类标签 Tags 

    splay翻转裸题

    #include<cstdio>
    #include<iostream>
    #define IN inline
    #define R register
    using namespace std;
    const int N=3e5+10;
    int n,rt,a[N],siz[N],fa[N],c[N][2],num[N];
    bool rev[N];
    IN int read(){
        R int x=0;R bool f=1;
        R char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    IN void updata(int k){
        int l=c[k][0],r=c[k][1];
        siz[k]=siz[l]+siz[r]+1;
    }
    IN void pushdown(int k){
        int &l=c[k][0],&r=c[k][1];
        if(rev[k]){
            swap(l,r);
            rev[l]^=1;rev[r]^=1;
            rev[k]=0;
        }
    }
    IN void rotate(int x,int &k){
        int y=fa[x],z=fa[y],l,r;
        l=(c[y][1]==x);r=l^1;
        if(y==k) k=x;
        else c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        updata(y);updata(x);
    }
    IN void splay(int x,int &k){
        while(x!=k){
            int y=fa[x],z=fa[y];
            if(y!=k){
                if((c[z][0]==y)^(c[y][0]==x)) rotate(x,k);
                else rotate(y,k); 
            }
            rotate(x,k);
        }
    }
    void build(int l,int r,int f){
        if(l>r) return ;
        int mid=l+r>>1; 
        c[f][mid>=f]=mid;
        siz[mid]=1;fa[mid]=f;
        if(l==r) return ;
        build(l,mid-1,mid);build(mid+1,r,mid);
        updata(mid);
    }
    int find(int k,int rk){
        pushdown(k);
        int l=c[k][0],r=c[k][1];
        if(siz[l]+1==rk) return k;
        return siz[l]>=rk?find(l,rk):find(r,rk-siz[l]-1);
    }
    IN void rever(int l,int r){
        int x=find(rt,l),y=find(rt,r+2);
        splay(x,rt);splay(y,c[x][1]);
        rev[c[y][0]]^=1;
    }
    int main(){
        n=read();
        for(int i=2;i<=n+1;i++) a[i]=read();
        build(1,n+2,0);rt=n+3>>1;
        for(int sum=0;sum<=10000;sum++){
            int mid=a[find(rt,2)];
            if(mid==1){
                printf("%d",sum);
                return 0;
            }
            rever(1,mid);
        }
        puts("-1");
        return 0;
    }
  • 相关阅读:
    多个类定义attr属性重复的问题:Attribute "xxx" has already been defined
    好用的批量改名工具——文件批量改名工具V2.0 绿色版
    得到ImageView中drawable显示的区域的计算方法
    得到view坐标的各种方法
    实现类似于QQ空间相册的点击图片放大,再点后缩小回原来位置
    Material Designer的低版本兼容实现(五)—— ActivityOptionsCompat
    Android 自带图标库 android.R.drawable
    解决 Attempting to destroy the window while drawing!
    解决Using 1.7 requires compiling with Android 4.4 (KitKat); currently using API 4
    Material Designer的低版本兼容实现(四)—— ToolBar
  • 原文地址:https://www.cnblogs.com/shenben/p/6195025.html
Copyright © 2011-2022 走看看