1743 反转卡片

漂亮妹子点击就送:http://codevs.cn/problem/1743/
 
题目描述 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。

 

并没有输出-1就A掉了

 

//这题不知道能不能直接按照它说的来做

//试一下

//在每个节点上记录这个点上的数字和数组下标
//查找现在树中最左边点的,如果它的数字==1,那就是完成了 
//否则就旋转。

//其实不用记录数字,只记录下标,然后去原数组中找对应下标的数字是几就可以 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=3e5+5;

int n;
int a[N];
struct NODE
{
    NODE *fa;
    NODE *son[2];
    int id,size;
    bool rev;
}node[N];

typedef NODE* Tree;
Tree Root,now_node,null;

inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}

inline void init()
{
    node->fa=node->son[0]=node->son[1]=node;
    Root=now_node=null=node;
}

inline Tree new_node(int id,Tree fa)
{
    ++now_node;
    now_node->id=id;
    now_node->fa=fa;
    now_node->son[0]=now_node->son[1]=null;
    return now_node;
}

inline void update(Tree root)
{
    root->size=root->son[0]->size+root->son[1]->size+1;
}

Tree build(Tree &root,int l,int r,Tree fa)
{
    if(l>r)
        return null;
    int mid=l+r>>1;
    root=new_node(mid-1,fa);
    if(l<r)
    {
        build(root->son[0],l,mid-1,root);
        build(root->son[1],mid+1,r,root);
    }
    update(root);
}

inline bool getgx(Tree root)
{
    return root->fa->son[1]==root;
}

inline void connect(Tree root,Tree fa,bool flag)
{
    if(fa!=null)
        fa->son[flag]=root;
    root->fa=fa;
}

inline void rotate(Tree root)
{
    Tree fa=root->fa;
    bool a=getgx(root),b=!a;
    connect(root->son[b],fa,a);
    connect(root,fa->fa,getgx(fa));
    connect(fa,root,b);
    update(fa);
    update(root);
    if(root->fa==null)
        Root=root;
}

inline void down(Tree root)
{
    if(root->rev)
    {
        swap(root->son[0],root->son[1]);
        if(root->son[0]!=null)
            root->son[0]->rev^=1;
        if(root->son[1]!=null)
            root->son[1]->rev^=1;
        root->rev=0;
    }
}

inline void splay(Tree root,Tree goal)
{
    down(root);
    for(;root->fa!=goal;rotate(root))
    {
        if(root->fa->fa!=goal)
            rotate(getgx(root)==getgx(root->fa)?root->fa:root);
    }
}

inline Tree find(Tree root,int pos)
{
    down(root);
    int left=root->son[0]->size;
    if(left+1==pos)
        return root;
    if(left>=pos)
        return find(root->son[0],pos);
    return find(root->son[1],pos-left-1);
}

inline void reverse(int l,int r)
{
    Tree a=find(Root,l),b=find(Root,r+2);
    splay(a,null);
    splay(b,a);
    b->son[0]->rev^=1;
}


int main()
{
    init();
    n=read();
    for(int i=1;i<=n;++i)
        a[i]=read();
    build(Root,1,n+2,null);
    Tree ans;
    for(int i=0;i<=100000;++i)
    {
        ans=find(Root,2);
        if(a[ans->id]==1)
        {
            printf("%d",i);
            exit(0);
        }
        reverse(1,a[ans->id]);
    }
    return 0;
}

 

posted @ 2018-04-10 13:54  whymhe  阅读(145)  评论(0编辑  收藏  举报