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; }