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

                             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。


    一道splay旋转区间

    之前写了bzoj3223: Tyvj 1729 文艺平衡树

    但是理解还不够深刻

    还没能透彻理解区间旋转

    因此刚开始找左数第一个数时写错了

    直接写成了tr[2].v(1是虚拟结点,翻转用的)

    而splay旋转时是直接修改树的左右孩子(感觉是类似于指针一样的东西,就是指向左右孩子的树根)

    所以tr[2].v可能会转到其他地方

    所以要先用find函数找到排名为2的结点的位置

    嗯,理解深刻多了

    (如有错误请大神指教)

    Ps:Sheldon帅炸啦!!!!!!

    #include<cstdio>
    #include<iostream>
    const int N=300050;
    struct node
    {
    	int fa,c[2],size,v,lazy;
    }tr[N];
    int n,root;
    void pushup(int k)
    {
    	tr[k].size=tr[tr[k].c[0]].size+tr[tr[k].c[1]].size+1;
    }
    void pushdown(int k)
    {
    	if(tr[k].lazy)
    	{
    		std::swap(tr[k].c[0],tr[k].c[1]);
    		tr[tr[k].c[0]].lazy^=1;
    		tr[tr[k].c[1]].lazy^=1;
    		tr[k].lazy=0;
    	}
    }
    void build(int l,int r,int fa)
    {
    	if(l>r)	return ;
    	if(l==r)
    	{
    		tr[l].fa=fa;tr[l].size=1;
    		if(l<fa)	tr[fa].c[0]=l;
    		else 		tr[fa].c[1]=l;
    	}
    	int mid=(l+r)>>1;
    	build(l,mid-1,mid);build(mid+1,r,mid);
    	tr[mid].fa=fa;pushup(mid);
    	if(mid<fa)	tr[fa].c[0]=mid;
    	else 		tr[fa].c[1]=mid;
    }
    void rotate(int x,int &k)
    {
    	int y=tr[x].fa,z=tr[y].fa,    l,r;
    	if(tr[y].c[0]==x)l=0;
    	else l=1;
    	r=l^1;
    	if(y==k)k=x;	
    	else 
    	{
    		if(tr[z].c[0]==y)tr[z].c[0]=x;
    		else tr[z].c[1]=x;
    	}
    	tr[x].fa=z;	tr[y].fa=x;
    	tr[tr[x].c[r]].fa=y;
    	tr[y].c[l]=tr[x].c[r];
    	tr[x].c[r]=y;
    	pushup(y);	pushup(x);
    }
    void splay(int x,int &k)
    {
    	while(x!=k)
    	{
    		int y=tr[x].fa,z=tr[y].fa;
    		if(y!=k)
    		{
    			if((tr[y].c[0]==x)^(tr[z].c[0]==y))	rotate(x,k);
    			else rotate(y,k);
    		}
    		rotate(x,k);
    	}
    }
    int find(int k,int rank)
    {
    	pushdown(k);
    	if(tr[tr[k].c[0]].size+1==rank)	return k;
    	if(tr[tr[k].c[0]].size+1>rank)	return find(tr[k].c[0],rank);
    	else return find(tr[k].c[1],rank-tr[tr[k].c[0]].size-1);
    }
    void dfs(int ro)
    {   
        pushdown(ro);
        if(tr[ro].c[0])dfs(tr[ro].c[0]);
        if(ro!=1&&ro!=n+2)printf("%d ",tr[ro].v);
        if(tr[ro].c[1])dfs(tr[ro].c[1]);
    }
    void rever(int l,int r)
    {
    	int x=find(root,l);
    	splay(x,root);
    	int y=find(root,r+2);
    	splay(y,tr[root].c[1]);
    	tr[tr[y].c[0]].lazy^=1;
    }
    int main()
    {
    	scanf("%d",&n); 
    	for(int i=1;i<=n;i++)
    	scanf("%d",&tr[i+1].v);
    	build(1,n+2,n+5);//该序列为   2  ~  n+1  
    	//额外节点为  1  和  n+2 
    	root=tr[n+5].c[0];
    	for(int ans=0;ans<=100000;ans++)
    	{
    		int k=tr[find(root,2)].v;
    		if(k!=1)	rever(1,k);
    		else 
    		{
    			printf("%d
    ",ans);
    			return 0;
    		}
    	}
    	printf("-1
    ");
    	return 0;
    }


  • 相关阅读:
    Linkerd 2.10(Step by Step)—将 GitOps 与 Linkerd 和 Argo CD 结合使用
    Linkerd 2.10(Step by Step)—多集群通信
    Linkerd 2.10(Step by Step)—使用 Kustomize 自定义 Linkerd 的配置
    Linkerd 2.10(Step by Step)—控制平面调试端点
    Linkerd 2.10(Step by Step)—配置超时
    Linkerd 2.10(Step by Step)—配置重试
    Linkerd 2.10(Step by Step)—配置代理并发
    本地正常运行,线上环境诡异异常原因集合
    Need to invoke method 'xxx' declared on target class 'yyy', but not found in any interface(s) of the exposed proxy type
    alpine 安装常用命令
  • 原文地址:https://www.cnblogs.com/Brian551/p/7353036.html
Copyright © 2011-2022 走看看