• bzoj 3211 花神游历各国 线段树区间开方


    题目大意

    给定一个序列,支持区间开方、区间求和

    \(n \leq 10^5,a_i \leq 10^9\)

    思路

    由于\(a_i \leq 10^9\),因此每一个元素至多开方五次就会变为1,因此每个点至多会被修改5次,复杂度\(O(nlogn)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 10;
    int a[N];
    #define ll long long
    
    struct node {
    	int l,r;
    	ll sum;
    	ll set;
    }t[N << 2];
    
    int read () {
    	int q = 0,f = 1;
    	char ch = getchar();
    	while(!isdigit(ch)) {
    		if(ch == '-')f = -1;
    		ch = getchar();
    	}
    	while(isdigit(ch)) {
    		q = q * 10 + ch - '0';
    		ch = getchar();
    	}return q * f;
    }
    
    void update(int rt) {
    	int ch = rt << 1;
    	t[rt].sum = t[ch].sum + t[ch + 1].sum;
    	t[rt].set = (t[ch].set && t[ch + 1].set);
    }
    
    void build(int l,int r,int rt) {
    	t[rt].l = l;
    	t[rt].r = r;
    	if (l == r) {
    		t[rt].sum = a[l];
    		t[rt].set = (a[l] <= 1);
    		return;
    	}
    	int mid = (l + r) >> 1;
    	int ch = rt << 1;
    	build(l,mid,ch);
    	build(mid + 1,r,ch + 1);
    	update(rt);
    }
    
    void modify(int l,int r,int rt) {
    	if(t[rt].set) { //优化,如果当前不需要开方就不开了
    		return;
    	}
    	if(t[rt].l == t[rt].r) {
    		t[rt].sum = (ll)sqrt(t[rt].sum + 0.5);
    		t[rt].set = t[rt].sum <= 1;
    	}
    	else {
    		int mid = (t[rt].l + t[rt].r) >> 1;
    		int ch = rt << 1;
    		if(r <= mid) {
    			modify(l,r,ch);
    		}else if(l > mid) {
    			modify(l,r,ch + 1);
    		}else {
    			modify(l,mid,ch);
    			modify(mid + 1,r,ch + 1);
    		}
    		update(rt);
    	}
    }
    
    
    ll query(int l,int r,int rt) {
    	//cout << l << ' ' << r << endl;
    	if(l <= t[rt].l and t[rt].r <= r) return t[rt].sum;
    	int mid = (t[rt].l + t[rt].r) >> 1;
    	ll res = 0;
    	int ch = rt << 1;
    	if(l <= mid) {
    		res += query(l,r,ch);
    	}
    	if(r > mid) {
    		res += query(l,r,ch + 1);
    	}
    	return res;
    }
    
    int n,m;
    
    int main () {
    	n = read();
    	for(int i = 1;i <= n; i ++) a[i] = read();
    	build(1,n,1);
    	m = read();
    	while(m --) {
    		int x,l,r;
    		x = read(),l = read(),r = read();
    		if(x == 1) {
    			printf("%lld\n",query(l,r,1));
    		}
    		else {
    			modify(l,r,1);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    独立思考模型与经验-仅供参考
    独立思考与输入、吸收
    基于事实和全方位思考
    独立思考有四个层次-知识体系
    思维框架
    阅读、思考与吸收
    思考与阅读
    博学之,审问之,慎思之,明辨之,笃行之:思考与成长
    如何成为有想法的人?如何培养独立思考的能力?
    人的本质--以人为本--思考-认识世界、改造世界
  • 原文地址:https://www.cnblogs.com/Allorkiya/p/15890301.html
Copyright © 2020-2023  润新知