题意:有一棵高为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
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;
}