Codeforces Round #312 (Div. 2) D. Guess Your Way Out! II

题意:有一棵高为h的树,出口在叶子节点上,n代表这棵树的高度,q代表q个判断,判断的样式是,i,L,R,ans,判断出口在第i层的祖宗节点是否在(L,R)中,ans == 0 代表不在,ans == 1 代表在。然后根据这q个判断,问:是否只有一个出口,如果只有一个出口,输出出口的位置,如果没有出口,输出Game cheated!,如果有多个出口,输出Data not sufficient!。
思路:首先查询只有10^5个,就代表可以把这些查询离散化了,每一个判断都是可以映射到叶子节点那一层,所以先把所有判断映射到叶子节点那一层,然后再离散化,这里离散注意一点就是如果两个点之间的距离大于2的话,需要在中间间隔两个点,因为在这题一个点和两个点是有区别的,两个点和更多点是没有区别的,离散化之后最多就只有4*10^5个点,所以就可以处理了。

http://codeforces.com/contest/558/problem/D

#include <map>
#include <queue>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 100005;
typedef long long LL;

struct Query {
    int r;
    LL x,y;
}q[MAXN];

int a[1000005];
long long A[1000005];
long long pos[1000005];
int n,m;
int tot = 0;
map<LL,int>mp;

void input() {
    int r,level;
    LL x,y;
    for(int i = 1 ; i <= m ; i++) {
        scanf("%d %I64d %I64d %d",&level,&x,&y,&r);
        for(int j = level + 1 ; j <= n ; j++) {
            x = x * (LL)2;
            y = y * (LL)2 + (LL)1;
        }
        q[i].x = x;
        q[i].y = y;
        q[i].r = r;
        A[i*2-1] = x;
        A[i*2] = y;
    }
}

void solve() {
    memset(a,0,sizeof(a));
    A[0] = (LL)1<<(n-1);
    sort(A+1,A+1+2*m);
    mp.clear();
    tot = 1;
    mp[A[0]] = 1;
    pos[tot] = A[1];
    A[2*m+1] = ((LL)1<<n)-(LL)1;
    for(int i = 1 ; i <= 2 * m + 1; i ++) {
        if(A[i] - A[i-1] > 2) {
            tot = tot + 3;
            mp[A[i]] = tot;
            pos[tot] = A[i];
        }
        else if(A[i] - A[i-1] == 2){
            tot = tot + 2;
            mp[A[i]] = tot; 
            pos[tot-1] = A[i] - 1;
            pos[tot] = A[i];
        }
        else if(A[i] - A[i-1] == 1) {
            tot = tot + 1;
            mp[A[i]] = tot;
            pos[tot] = A[i];
        }
    }
    for(int i = 1 ; i <= m ; i++) {
        int x = mp[q[i].x];
        int y = mp[q[i].y];
        if(q[i].r == 1) {
            a[1] ++;
            a[x] --;
            a[y+1] ++;
            a[tot+1] --;
        }
        else {
            a[x] ++;
            a[y+1] --;
        }
    }
    int cnt = 0;
    int position;
    for(int i = 1 ; i <= tot ; i++) {
        a[i] += a[i-1];
        if(a[i] == 0) {
            cnt ++;
            position = i;
        }
    }
    if(cnt == 0) {
        puts("Game cheated!");
    }
    else if(cnt >= 2){
        puts("Data not sufficient!");
    }
    else {
        if(n == 1) {
            puts("1");
            return ;
        }
        printf("%I64d\n",pos[position]);
    }
}

int main(void) {
    //freopen("a.in","r",stdin);
    while(~scanf("%d %d",&n,&m)) {
        input();
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值