题面
Amr bought a new video game "Guess Your Way Out! II". The goal of the game is to find an exit from the maze that looks like a perfect binary tree of height h. The player is initially standing at the root of the tree and the exit from the tree is located at some leaf node.
Let's index all the nodes of the tree such that
- The root is number 1
- Each internal node i (i ≤ 2h - 1 - 1) will have a left child with index = 2i and a right child with index = 2i + 1
The level of a node is defined as 1 for a root, or 1 + level of parent of the node otherwise. The vertices of the level h are called leaves. The exit to the maze is located at some leaf node n, the player doesn't know where the exit is so he has to guess his way out!
In the new version of the game the player is allowed to ask questions on the format "Does the ancestor(exit, i) node number belong to the range [L, R]?". Here ancestor(v, i) is the ancestor of a node v that located in the level i. The game will answer with "Yes" or "No" only. The game is designed such that it doesn't always answer correctly, and sometimes it cheats to confuse the player!.
Amr asked a lot of questions and got confused by all these answers, so he asked you to help him. Given the questions and its answers, can you identify whether the game is telling contradictory information or not? If the information is not contradictory and the exit node can be determined uniquely, output its number. If the information is not contradictory, but the exit node isn't defined uniquely, output that the number of questions is not sufficient. Otherwise output that the information is contradictory.
Input
The first line contains two integers h, q (1 ≤ h ≤ 50, 0 ≤ q ≤ 105), the height of the tree and the number of questions respectively.
The next q lines will contain four integers each i, L, R, ans (1 ≤ i ≤ h, 2i - 1 ≤ L ≤ R ≤ 2i - 1, ), representing a question as described in the statement with its answer (ans = 1 if the answer is "Yes" and ans = 0 if the answer is "No").
Output
If the information provided by the game is contradictory output "Game cheated!" without the quotes.
Else if you can uniquely identify the exit to the maze output its index.
Otherwise output "Data not sufficient!" without the quotes.
Examples
Input
3 1 3 4 6 0
Output
7
Input
4 3 4 10 14 1 3 6 6 0 2 3 3 1
Output
14
Input
4 2 3 4 6 1 4 12 15 1
Output
Data not sufficient!
Input
4 2 3 4 5 1 2 3 3 1
Output
Game cheated!
Note
Node u is an ancestor of node v if and only if
- u is the same node as v,
- u is the parent of node v,
- or u is an ancestor of the parent of node v.
In the first sample test there are 4 leaf nodes 4, 5, 6, 7. The first question says that the node isn't in the range [4, 6] so the exit is node number 7.
In the second sample test there are 8 leaf nodes. After the first question the exit is in the range [10, 14]. After the second and the third questions only node number 14 is correct. Check the picture below to fully understand.
题目链接
参考链接
Codeforces Round #312 (Div. 2) D. Guess Your Way Out! II (求区间的补、交)author:fukan
题目简述
这是一个完全二叉树一共有h层,其中一个叶子结点是迷宫的出口,现在需要根据题目提供的q次询问和答案来判断出口的位置。
对于每个询问,问:“出口在第i层的祖先”的序号在[L,R]之间吗?(L、R与“出口在第i层的祖先”在同一层)如果是,ans=1,否则ans=0。
先根据i,L,R处理出在叶子结点层对应的区间[L,R](以下L,R均为处理过的),对于这些区间依次进行如下操作:
①对于ans==1的询问,则一个个地与已有答案answer取交集(answer的初始值为全集)
②对于ans==0的询问,得到两根扫描线:
第一根:位置在L,标记值为1
第二根:位置在R,标记值为-1
对于所有扫描线重新排序,遍历这些线,用sign记录标记值得前缀和。
当sign==0时,说明经过的扫描线数目为偶数,标记值为1和-1的线各一半,即经过若干个完整的区间。那么当前扫描线和下一根扫描线之间的区间,一定是(ans==0的区间的并集相对于全集的)补集的一部分。将这个区间与“操作①”得到的结果求交集。
一定要区分以下两种情况:(Wrong answer on test 11)
①没有ans==0的询问,即line_num==0。调用了操作②的函数,造成无解的假象。
②有ans==0的询问,但把全集覆盖了,造成无解。
程序分析
int h;
struct Node/**区间**/
{
long long left,right;
}node[maxn];
int node_num;
struct Line/**扫描线**/
{
long long where;
int flag;
}line[maxn*2];
int line_num;
bool cmp_line(const Line &a,const Line &b)/**扫描线排序规则**/
void read(int i,long long L,long long R,int ans)/**对于每个询问进行初步处理**/
Node deal_positive()/**处理ans==1的询问**/
Node deal_negative(Node x)/**处理ans==0的询问**/
Node work()
answer.left==-1无解
answer.left==-2信息不足/有多个解
程序
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 100005
int h;
struct Node/**区间**/
{
long long left,right;
}node[maxn];
int node_num;
struct Line/**扫描线**/
{
long long where;
int flag;
}line[maxn*2];
int line_num;
bool cmp_line(const Line &a,const Line &b)/**扫描线排序规则**/
{
if(a.where!=b.where)
return a.where<b.where;
else
return a.flag<b.flag;
}
void read(int i,long long L,long long R,int ans)/**对于每个询问进行初步处理**/
{
for(int j=i+1;j<=h;j++)
{
L*=2;
R=R*2+1;
}
if(ans==1)
{
node[node_num].left=L;
node[node_num].right=R;
node_num++;
}
else
{
line[line_num].flag=1;
line[line_num].where=L;
line_num++;
line[line_num].flag=-1;
line[line_num].where=R;
line_num++;
}
}
Node deal_positive()/**处理ans==1的询问**/
{
Node answer;
answer.left=1;
answer.right=1;
for(int i=2;i<=h;i++)
{
answer.left*=2;
answer.right=answer.right*2+1;
}
for(int i=0;i<node_num;i++)
{
answer.left=max(answer.left,node[i].left);
answer.right=min(answer.right,node[i].right);
if(answer.left>answer.right)
{
answer.left=answer.right=-1;/**无解**/
return answer;
}
}
return answer;
}
Node deal_negative(Node x)/**处理ans==0的询问**/
{
int sign=0;
Node answer;
answer.left=answer.right=-1;
Node temp;
temp.left=1;
for(int i=2;i<=h;i++)
temp.left*=2;
temp.right=line[0].where-1;
if(temp.left<=temp.right&&max(x.left,temp.left)<=min(x.right,temp.right))/**最左端点到第一根扫描线之间的区间**/
{
answer.left=max(x.left,temp.left);
answer.right=min(x.right,temp.right);
}
for(int i=0;i<line_num;i++)
{
sign+=line[i].flag;
if(sign==0)/**当前扫描线到下一根扫描线之间的区间**/
{
temp.left=line[i].where+1;
if(i==line_num-1)
{
temp.right=1;
for(int i=2;i<=h;i++)
temp.right=temp.right*2+1;
}
else
temp.right=line[i+1].where-1;
if(temp.left<=temp.right&&max(x.left,temp.left)<=min(x.right,temp.right))
{
if(answer.left!=-1)
{
answer.left=answer.right=-2;
return answer;
}
answer.left=max(x.left,temp.left);
answer.right=min(x.right,temp.right);
}
}
}
return answer;
}
Node work()
{
Node answer=deal_positive();
if(answer.left==-1)
return answer;
if(line_num>0)
answer=deal_negative(answer);
if(answer.left!=answer.right)
{
answer.left=answer.right=-2;
}
return answer;
}
int main()
{
int q;
node_num=0;
line_num=0;
scanf("%d%d",&h,&q);
while(q--)
{
int i,ans;
long long L,R;
scanf("%d%lld%lld%d",&i,&L,&R,&ans);
read(i,L,R,ans);
}
sort(line,line+line_num,cmp_line);
Node answer=work();
if(answer.left==-1)
printf("Game cheated!");
else if(answer.right==-2)
printf("Data not sufficient!");
else
printf("%lld\n",answer.left);
return 0;
}