很好的题
思路参考网上的
首先我们每次处理都直接推到叶子节点
确定的区间我们可以分成两个可能的区间。
比如l,r 确定没有 那么可能的区间就是 l[n],l-1 r+1,r[n]
那么就转化为了有多少个点被覆盖q次的问题了,因为区间太大,我们用map做。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define FOR(i,a,b) for(long long i=a;i<=b;i++)
#define ROF(i,a,b) for(long long i=a;i>=b;i--)
#define mem(i,a) memset(i,a,sizeof(i))
#define rson mid+1,r,rt<<1|1
#define lson l,mid,rt<<1
#define mp make_pair
#define pb push_back
#define ll long long
#define LL long long
using namespace std;
template <typename T>inline void read(T &_x_){
_x_=0;bool f=false;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=!f;ch=getchar();}
while ('0'<=ch&&ch<='9') {_x_=_x_*10+ch-'0';ch=getchar();}
if(f) _x_=-_x_;
}
const double eps = 1e-8;
const int maxn = 1e5+7;
const int mod = 1e9+7;
const ll inf = 1e15;
ll L[55],R[55];
ll n,q,x,y,z,v;
map<ll, int >mmp;
int main(){
L[1] = R[1] = 1;
for(int i=2;i<=50;i++){
L[i]=L[i-1]<<1;
R[i]=R[i-1]<<1|1;
}
read(n),read(q);
if(q == 0){
if (n == 1)printf("1\n");
else printf("Data not sufficient!\n");
return 0;
}
FOR(i,1,q){
read(x),read(y),read(z),read(v);
while(x<n){
y<<=1;
z=z<<1|1;
x++;
}
if(v){
mmp[y]++, mmp[z+1]--;
}else{
mmp[L[n]]++, mmp[y]--;
mmp[z+1]++, mmp[R[n]+1]--;
}
}
int sum = 0;
ll pre = -1, cnt = 0, ans = 0;
for(auto i = mmp.begin(); i != mmp.end(); i++){
sum += i->second;
if(pre != -1){
cnt += i->first-pre;
ans = pre;
}
if(sum == q) pre = i->first;
else pre = -1;
}
if (cnt == 0)printf("Game cheated!\n");
else if (cnt > 1)printf("Data not sufficient!\n");
else printf("%I64d\n", ans);
return 0;
}