codeforces #312 558D D. Guess Your Way Out! II(排序离散化)

本文介绍了一种解决完全二叉树出口判断问题的方法。通过将各层节点映射到最后一层,转换真假条件,最终确定唯一的出口节点或判断条件是否矛盾。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:

点击打开链接

题目大意:

给出一棵完全二叉树,告诉你出口在某一层的哪些点的子树中(出口一定在树的最后一层),问它给出的提示是否矛盾,如果不矛盾,能否判断出哪个点是出口

题目分析:

首先它给出不管是哪一层的点,都可以换算到最后一层,利用二叉树的性质当前层的l-r的区间,对应到下一层就是2*l-1到2*r,那么就可以一直推到最底层,然后把真的条件,可以换成两个假的条件,然后最后就可以得到所有假的区间,然后对这些区间按照区间左边界排序,然后遍历所有区间,记录当前最左的目前认为是出口的值,然后统计所有可能是出口的值的总数,每次扫描到一个区间,因为它的左边界最小,所以如果当前的最左可能是出口到左边界的间隔不为0,那么这段就判断是出口,t统计,然后更新最左可能是入口的值到达当前区间的右边界加1,注意是可能,之前的点都已经判断为一定是出口,或一定不是,那么扫描到最后,如果t==0,那么说明没有出口了,所以矛盾了,如果t>1.那么说明没有唯一解,其余情况输出维护的那个答案即可

代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 57
#define M 400007

using namespace std;

typedef long long LL;
typedef pair<LL,LL> PII;

int h,q;
LL sum[MAX];
LL two[MAX];

void init ( )
{
    two[1] = 1;
    for ( int i = 2 ; i < MAX ; i++ )
        two[i] = two[i-1]<<1;
    sum[0] = 0;
    for ( int i = 1 ; i < MAX ; i++ )
        sum[i] = sum[i-1] + two[i];
}

PII p[M];
int cnt;

int main ( )
{
    int a,f;
    LL l,r;
    init();
    while ( ~scanf ( "%d%d" , &h , &q ) )
    {
        cnt = 0;
        while ( q-- )
        {
           scanf ( "%d%I64d%I64d%d" , &a , &l , &r , &f );
           l -= sum[a-1];
           r -= sum[a-1];
           int temp = a;
           while ( temp < h )
           {
               l = l*2-1;
               r = r*2;
               temp++;
           }
           if ( f == 0 ) p[cnt++] = make_pair ( l , r );
           else
           {
               if ( l > 1 )
                    p[cnt++] = make_pair ( 1 , l-1 );
               if ( r < two[h] )
                    p[cnt++] = make_pair ( r+1 , two[h] );
           }
        }
        sort ( p , p+cnt );
        //cout << p[0].first << " " << p[0].second << endl;
        LL ans = -1 , loc = 1 , t = 0;
        for ( int i = 0 ; i < cnt ; i++ )
        {
            if ( p[i].first > loc )
            {
                ans = loc;
                t += p[i].first - loc;
            }
            loc = max ( loc , p[i].second+1 );
        }
        if ( two[h] >= loc )
        {
            ans = loc;
            t += two[h] - loc + 1;
        }

        //cout << "YES : " << t << endl;

        if ( t == 0 )
            puts ("Game cheated!");
        else if ( t > 1 )
            puts ("Data not sufficient!");
        else printf ( "%I64d\n" , ans + sum[h-1]);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值