• HZNUOJ ACM实验室暑期考核 F B_M的斐波那契 线段树/树状数组


    题意

    给一个长度为(n)(a) 数组,初始时(a_i = 1) ,有两个操作

    • (l-r) 区间内(a_i += 1)
    • 询问(l-r) 区间(a_i) 作为斐波那契数列下标的数值和是否$ geq k quad$ ($ k leq 10^{10})$

    分析

    如果直接线段树区间修改显然是做不到的,不妨换一种思路

    注意到(f_{50} geq 10^{10}) ,这意味着一个点一旦被加了超过(50) 次,就没必要修改这个点了。

    这样就考虑怎么高效的删除这些不需要的点。

    考虑用set 存放(1-n) 的下标,一旦某个下标的斐波那契数列项数超过了(50) 就删除这个节点。这样一来

    就是一个单点修改(注意一个点最多被修改50次) ,区间求和

    于是就可以用树状数组或者线段树维护了

    ll fib[55] = { 0, 1 };
    int n, m;
    int num[maxn << 2];
    ll sum[maxn << 2];
    set<int> st;
    
    void pushUp(int i) {
    	sum[i] = sum[i << 1] + sum[i << 1 | 1];
    }
    
    void update(int pos, int l, int r, int i) {
    	if (l == pos && r == pos) {
    		num[i]++;
    		sum[i] = fib[num[i]];
    		if (num[i] == 50) st.erase(pos);
    		return;
    	}
    	int mid = l + r >> 1;
    	if (pos <= mid) update(pos, l, mid, i << 1);
    	else update(pos, mid + 1, r, i << 1 | 1);
    	pushUp(i);
    }
    
    int res;
    void query(int l, int r, int i, int L, int R) {
    	if (L <= l && R >= r) {
    		res += sum[i];
    		return;
    	}
    	int mid = l + r >> 1;
    	if (L <= mid) query(l, mid, i << 1, L, R);
    	if (R > mid) query(mid + 1, r, i << 1 | 1, L, R);
    }
    
    void range_update(int l, int r) {
    	auto begin = st.lower_bound(l);
    	auto end = st.upper_bound(r);  //这里用了upper -1就一定是范围里了
    	if (end != st.end()) end--;
    	for (auto it = begin; it != end; it++) {
    		update(*it, 1, n, 1);
    	}
    }
    
    int main() {
    	for (int i = 2; i < 55; i++) fib[i] = fib[i - 1] + fib[i - 2];
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++) update(i, 1, n, 1), st.insert(i);
    	while (m--) {
    		int op;
    		scanf("%d", &op);
    		if (op == 1) {
    			int l, r;
    			scanf("%d%d", &l, &r);
    			range_update(l, r);
    		}
    		else {
    			int l, r;
    			ll k;
    			scanf("%d%d%lld", &l, &r, &k);
    			res = 0;
    			query(1, n, 1, l, r);
    			puts(k <= res ? "YES" : "NO");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    SQLSERVER服务器配置
    JS中的call()和apply()方法 青青
    JS || && 青青
    map() 和 forEach() 区别 兼容写法 青青
    ECMAScript arguments 对象 青青
    jsonp 青青
    Tomcat工作原理
    C博客作业02循环结构
    c语言第0次作业
    C语言博客作业03函数
  • 原文地址:https://www.cnblogs.com/hznumqf/p/13562420.html
Copyright © 2020-2023  润新知