zoukankan      html  css  js  c++  java
  • SPOJ GSS4 (区间开根号 + 区间查询) (线段树)

    SPOJ GSS4 (区间开根号 + 区间查询) (线段树)

    传送门

    题目大意:

    对于给定的(n)个数的序列,我们定义两个操作,分别是区间开根号以及区间求和。共有(m)次查询,其中(n,mleq1e5,sum_{i=1}^na_ileq1e18)

    我们会发现一个神奇的事情(然而并不神奇),就是一个数多开几次平方就变成1了,一个(1e18)以内的数,开最多6次就是1,也就是说,每一个叶子节点最多只会被更新六次,所以我们用线段树维护区间最大值和区间和,对于区间最大值为1的区间就不再做任何开方操作,对于需要开平方的区间,正常更新到叶子节点,因为最多一个节点会被更新6次,这样的话这个题就解决了。

    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 2e5 + 5;
    using namespace std;
    inline LL read() {
    	LL s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    LL a[N]; 
    namespace Segment{
    	#define ls k<<1
    	#define rs k<<1|1
    	struct node{
    	    int l,r,v;
    	    LL sum,Max;
    	}t[N<<2];
    	void build(int k, int l, int r){
    	    t[k].l = l,t[k].r = r;
    	    if(l == r){
    	        t[k].Max = a[l];
    	        t[k].sum  = a[l];
    	        return ;
    	    }
    	    int mid = l+r>>1;
    	    build(ls,l,mid),build(rs,mid + 1,r);
    	    t[k].sum = t[ls].sum + t[rs].sum;
    	    t[k].Max = max(t[ls].Max,t[rs].Max);
    	}
    	void update(int k, int l, int r){
    	    int mid = (t[k].l + t[k].r)>>1;
    	    if(t[k].l == t[k].r){
    	        t[k].Max = sqrt(t[k].Max);
    	        t[k].sum = sqrt(t[k].sum);
    	        return ;
    	    }
    	    if(t[k].Max == 1) return ;
    	    if(r <= mid) update(ls,l,r);
    	    else if(l > mid) update(rs,l,r);
    	    else update(ls,l,mid),update(rs,mid + 1,r);
    	    t[k].sum = t[ls].sum + t[rs].sum;
    	    t[k].Max = max(t[ls].Max,t[rs].Max);
    	}
    	LL query(int k, int l, int r){
    	    if(t[k].l == l && t[k].r == r) return t[k].sum;
    	    int mid = (t[k].l+t[k].r) >> 1;
    	    if(r <= mid) return query(ls,l,r);
    	    else if(l > mid) return query(rs,l,r);
    	    else return query(ls,l,mid) + query(rs,mid + 1,r);
    	}
    }
    using namespace Segment;
    int n,m,cas;
    int main(){
        while(scanf("%lld",&n) != EOF){
            for(int i = 1;i <= n;i++) a[i] = read();
            build(1,1,n);
            m =	read();
         	printf("Case #%d:
    ",++cas);
            for(int i = 1;i <= m;i++){
                int op = read(),l = read(),r = read();
                if(l > r) swap(l,r);
                if(op == 0) update(1,l,r);
                else if(op == 1) printf("%lld
    ",query(1,l,r));
            }
            puts("");
        }
        return 0;
    }
    
  • 相关阅读:
    Python 存储引擎 数据类型 主键
    Python 数据库
    Python 线程池进程池 异步回调 协程 IO模型
    Python GIL锁 死锁 递归锁 event事件 信号量
    Python 进程间通信 线程
    Python 计算机发展史 多道技术 进程 守护进程 孤儿和僵尸进程 互斥锁
    Python 异常及处理 文件上传事例 UDP socketserver模块
    Python socket 粘包问题 报头
    Django基础,Day7
    Django基础,Day6
  • 原文地址:https://www.cnblogs.com/excellent-zzy/p/12404249.html
Copyright © 2011-2022 走看看