fib[50] > 1e10;
所以在结构体中定义一个数组 存放区间内 各个fib下标的数量
如果存在点下标大于等于50, 标记一下即可
代码很长, 写的时候很随意, 看的时候很恶心
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
inline ll rd() {
ll x = 0, f = 1; char ch = getchar();
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
return x * f;
}
ll fib[60], have, ans;
int op, l, r;
bool flag = false;
void init(){
fib[0] = 0;
fib[1] = 1;
int cnt;
for(cnt = 2; fib[cnt-1] <= 1e10; ++ cnt)
fib[cnt] = fib[cnt-1] + fib[cnt-2];
//fib[50] > 1e10
}
struct node{
int l, r, w[50];
int f;
bool over;
}tree[maxn<<2];
void down(int k){
if(tree[k].f){
tree[k<<1].f += tree[k].f;
tree[k<<1|1].f += tree[k].f;
if(tree[k].f >= 49) tree[k].over = true;
if(tree[k<<1].f >= 49) tree[k<<1].over = true;
if(tree[k<<1|1].f >= 49) tree[k<<1|1].over = true;
for(int i = 49; i >= tree[k].f; -- i){
if(!tree[k<<1].over && i + tree[k].f >= 50 && tree[k<<1].w[i] > 0)
tree[k<<1].over = true;
if(!tree[k<<1|1].over && i + tree[k].f >= 50 && tree[k<<1|1].w[i] > 0)
tree[k<<1|1].over = true;
tree[k<<1].w[i] = tree[k<<1].w[i-tree[k].f];
tree[k<<1].w[i-tree[k].f] = 0;
tree[k<<1|1].w[i] = tree[k<<1|1].w[i-tree[k].f];
tree[k<<1|1].w[i-tree[k].f] = 0;
}
tree[k].f = 0;
}
}
void build(int k, int l, int r){
tree[k].l = l, tree[k].r = r;
tree[k].over = false, tree[k].f = 0;
memset(tree[k].w, 0, sizeof tree[k].w);
if(l == r){
tree[k].w[1] = 1;
return;
}
int mid = (l+r) >> 1;
build(k<<1, l ,mid);
build(k<<1|1, mid+1, r);
tree[k].w[1] = r-l+1;
}
void updata(int k, int l, int r){
if(tree[k].l >= l && tree[k].r <= r){
tree[k].f += 1;
if(tree[k].f >= 49)
tree[k].over = true;
if(tree[k].w[49] > 0)
tree[k].over = true;
for(int i = 49; i >= 1; -- i){
tree[k].w[i] = tree[k].w[i-1];
}
return;
}
down(k);
int mid = (tree[k].l + tree[k].r) >> 1;
if(l <= mid) updata(k<<1, l, r);
if(r > mid) updata(k<<1|1, l, r);
for(int i = 1; i < 50; ++ i){
tree[k].w[i] = tree[k<<1].w[i] + tree[k<<1|1].w[i];
if(!tree[k].over)
tree[k].over = (tree[k<<1].over || tree[k<<1|1].over);
}
}
void query(int k, int l, int r){
if(flag) return;
if(tree[k].l >= l && tree[k].r <= r){
if(tree[k].over){
flag = true;
return;
}
for(int i = 1; i <= 49; ++ i){
have += fib[i] * tree[k].w[i];
if(have >= ans){
flag = true;
return;
}
}
return;
}
down(k);
int mid = (tree[k].l + tree[k].r) >> 1;
if(l <= mid) query(k<<1, l, r);
if(r > mid) query(k<<1|1, l, r);
}
int main(){
init();
int n, m;
n = rd(); m = rd();
build(1, 1, n);
for(int i = 0; i < m; ++ i){
op = rd(); l = rd(); r = rd();
if(op == 1){
updata(1, l, r);
}
if(op == 2) {
ans = rd();
have = 0;
flag = false;
query(1, l, r);
puts(flag ? "YES" : "NO");
}
}
return 0;
}