Codeforces Round #287 (Div. 2) C. Guess Your Way Out!

C. Guess Your Way Out!

题意:给一个深为h的树(从0层开始),从root以"LRLRLRLR..."的指令顺序,问道最后一层第n个节点需要遍历的节点个数。

  • Character 'L' means "go to the left child of the current node";
  • Character 'R' means "go to the right child of the current node";
  • If the destination node is already visited, Amr skips current command, otherwise he moves to the destination node;
  • If Amr skipped two consecutive commands, he goes back to the parent of the current node before executing next command;
  • If he reached a leaf node that is not the exit, he returns to the parent of the current node;
  • If he reaches an exit, the game is finished.

题解:题意没怎么懂,走法叙述的好复杂,但下面有张图给了我想法;

看图可以发现几条性质:
1、任何node的 左子节点都是偶数,右子节点都是奇数;
2、若当前节点是 偶数则先走向右子节点,奇数则先走向左子节点;
3、考虑每个子树 记高h的最底层节点个数的一半为mid(有mid=1<<(h-1);):
   若子树的root是奇数:①当n>mid,则会先走完root的左半边(即ans加上(1<<h)个节点),
                         且走到右半边子树root仍为奇数,
                         但在右子树中EXIT的相对位置减少mid;
                         (即图中E在以9为根的树中,在最下层的第(n-mid=6-4=)2位置);
                       当n<=mid,就直接进入左半边,但子树root变为偶数,
                         加上根节点ans++ ,而EXIT相对位置不变;
   
   若子树的root是偶数:当n>mid,则EXIT在右子树中,且子树根节点变为奇数,
                         加上根节点ans++ ,EXIT相对位置n=n-mid ;
                       当n<=mid,则先会走完root的右半边即ans加上(1<<h)个节点;
                         root仍为偶数,      EXIT相对位置不变;

不语,一切尽在代码中:

#define INF 0x7fffffff
#define eps (1e-9)
#define maxn 1000000000
#define clearto(s,x) memset(s,x,sizeof(s))
using namespace std;

int m,h,tot=0;
long long n,mid;
int main()
{
    //freopen("E:\DATA.txt","r",stdin);
    //int TT=1,tt+=1;            scanf("%d",&TT);
    int i=0,j=0;
    long long ans=0;
    scanf("%d %I64d",&h,&n);
    int root=1,odd=1,even=2;
    while(h>0)
    {                            //不强制转换大数花挂 ::>_<::
        mid=(long long)1<<(h-1);
        if(root==odd)
        {
           if(n> mid)
           {  ans+=(mid*2);  h--;    n=n-mid;      }
           else
           {  root=even;     ans+=1;     h--;      }
           continue;
        }
        if(root==even)
        {
           if(n> mid)
           {  root=odd;      ans++; h--; n=n-mid;  }
           else
           {  ans+=(mid*2);         h--;           }
        }
    }
    printf("%I64d",ans);
    return 0;
}


                       


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值