URAL 1088|Ilya Murometz|位运算|满二叉树的性质|LCA

11 篇文章 0 订阅
8 篇文章 0 订阅

http://acm.timus.ru/problem.aspx?space=1&num=1088
严重吐槽本题阅读理解。。。

题目

不幸 降临在俄国的土地上。恶魔掠走了Ilya的同伴Alyosha Popovich,并把他拴在魔石上,这样Alyosha就不能移动了。救出被囚禁的Alyosha是很有必要的,但是没人能做到。英雄Tsar被派去打仗了。Ilya Murometz对自己说:“我要一个人救出我的朋友Alyosha,如果他死在那了,我也一起死。”Ilya说玩就跳上它的马去找Alyosha了。
Ilya骑着它的马走到了一个石头前,但是不是他要找的那个魔石,而是一个指路石,上面写着,如果你向左走,你将得到”时间限制”,如果你向右走,你将获得”错误的答案”(这里不是很理解这段话意义何在。。)Ilya崩溃地瘫坐下来。突然一只小鸟停在他身边对他说:“你为什么沮丧呢?我的好朋友”Ilya告诉小鸟他的困难后小鸟说:“这里就是这样的:如果你向左走,1小时后你还会见到长这样的石头,知道你走到大海。是恶魔捣的鬼,他希望你在这里迷路。回去吧,Ilya,不要死在这!”然后小鸟的消失了,毕竟这里本来就没有小鸟。Ilya想了很久,但是又不希望背叛与Alyosha的友谊,他又骑上了马并继续旅程。骑着骑着骑了很久。
Ilya在一个跟第一个石头长得很像的石头旁跳下了马,又开始沮丧,而且比第一次还严重。突然他就看见了魔石(玄学。。),而且离他不远,但是他又不能离开道路,否则他就会被沼泽淹没。他看见大海离他很近,他甚至可以算出魔石离大海的距离为 D 小时的路程;他自己到大海则需要E小时的路程。从最开始的石头到大海的距离为 F 小时的路程(这个是他父亲告诉他的)。
他看见道路是通向码头的,码头用连续的整数标号。Ilya令从最开始的石头一直往右走走到的码头为1号,到1号码头前往左走走道的码头为2号,以此类推。Ilya看见离他最近的码头为Ep号,离魔石最近的码头为 Dp 号(视力真好。。)他的马告诉他自己只能走 H 小时的路程了。请你帮助Ilya Murometz判断他能拯救Alyosha Popovich,还是留在这偏僻的远方。
Problem illustration

输入

输入一行6个整数:D,E,F,Dp,Ep,H,其中 0D,E,F,H30 1Ep,Dp1,073,741,824

输出

如果Ilya能到达魔石,输出”YES”,否则输出”NO”。

样例输入

1 2 3 2 6 4

样例输出

YES

题解

magic stone就是Alyosha的位置啦。
然后 D 表示到离Alyosha最近的满二叉树叶节点的距离,E表示Ilya到最近的叶节点的距离, F 表示根节点到叶节点的距离,Dp表示Alyosha到最近的叶节点的编号(当然可以有多个,这里只给一个), Ep 表示Ilya到最近的叶节点的编号, H 表示Ilya最远能走几条边。

以下为一大堆废话,dalao请跳过。

由于是满二叉树,所以叶节点的编号就可以表示其位置了,比如5号节点,减去1后的二进制表示法为(4)10=(100)2,表示先走右儿子再走两次左儿子,即0表示左儿子,1表示右儿子。然后求LCA的层数(因为没有标号,也没有必要给标号,求LCA一般求其到根节点距离,也就是层数)也很简单,只要求两个点标号减一后的二进制表示法前几位最多有多少位相同即可。比如1和4的标号是 (0)10=(000)2;(3)10=(011)2 ,有1位相同(0),所以1号和4号的LCA为第2层(如果没有相同的为第1层,即层数为相同数字+1)。

然后知道了LCA就可以算Alyosha和Ilya之间的距离了,然后就没有然后了。

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

int main() {
    char ans[2][4] = { "NO", "YES" };
    int d, e, f, dp, ep, h, dep = 0;
    scanf("%d%d%d%d%d%d", &d, &e, &f, &dp, &ep, &h);

    for (--dp, --ep; dp != ep; dp /= 2, ep /= 2)
        ++dep;

    if (dep <= max(d, e)) // 如果LCA为两者其中之一
        puts(ans[abs(d - e) <= h]);
    else // 否则
        puts(ans[dep * 2 - d - e <= h]);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值