zoukankan      html  css  js  c++  java
  • GSS问题(二)

    GSS问题(二)

    仍然是线段树的应用模板题,非常经典

    题面

    (n)个数,(nleqslant1e5),和(leqslant10^{18}),全是自然数

    翻译:long long能过

    给出两种操作:

    • 区间开方( ightarrow)将区间每一个数单独开方,下取整
    • 区间求和( ightarrow)将区间所有书加起来求和

    作为模板题,我自己给出一个条件:最好用线段树做[doge]

    原题还有这样一句话:

    image-20200517180233452

    mmp这个造数据的比我还懒

    对于细节处理问题,比如上面这张图所出现的问题就不再讲,主要是看如何用线段树实现主要操作

    思路

    显然,开方这个操作并不能直接对于整个区间进行

    那咋办嘛?

    那只能单个元素开方了

    每次操作都对每一个元素进行开方,非常费时间,

    但是我们知道开方可以使一个数非常快的变小,直至1,除非本来就是0或者1

    那么到了0或1的时候,就无须再开方,

    不妨这样考虑:

    对于每一个树节点,开设变量(maxn)来保存区间最大值,如果区间最大值为1或0,显然整个区间就无须开方,直接跳过,大大优化了复杂度

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define ll long long
    #define ci const int &
    using namespace std;
    const int N=100005;
    ll a[N];
    ll sum[N<<2],maxn[N<<2];
    inline void build(ci k,ci l,ci r){
    	if(l==r){
    		sum[k]=a[l];
    		maxn[k]=a[l];
    		return ;
    	}int mid=l+r>>1;
    	build(k<<1,l,mid);
    	build(k<<1|1,mid+1,r);
    	sum[k]=sum[k<<1]+sum[k<<1|1];
    	maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
    }
    inline void insert(ci k,ci l,ci r,ci x,ci y){
    	if(maxn[k]<=1) return ;
    	if(l==r){
    		sum[k]=(ll)(sqrt(sum[k]));
    		maxn[k]=(ll)(sqrt(maxn[k]));
    		return ;
    	}int mid=l+r>>1;
    	if(x<=mid) insert(k<<1,l,mid,x,y);
    	if(mid<y) insert(k<<1|1,mid+1,r,x,y);
    	sum[k]=sum[k<<1]+sum[k<<1|1];
    	maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
    }
    inline ll query(ci k,ci l,ci r,ci x,ci y){
    	if(x<=l&&r<=y) return sum[k];
    	int mid=l+r>>1;
    	ll ret=0;
    	if(x<=mid)  ret+=query(k<<1,l,mid,x,y);
    	if(mid<y) ret+=query(k<<1|1,mid+1,r,x,y);
    	return ret;
    }int n,m;
    int cnt;
    int main(){
    	while(scanf("%d",&n)!=EOF){
    		printf("Case #%d:
    ",++cnt);
    		for(int i=1;i<=n;i++)
    			scanf("%lld",&a[i]);
    		build(1,1,n);
    		scanf("%d",&m);
    		while(m--){
    			int n1,n2,n3;
    			scanf("%d%d%d",&n1,&n2,&n3);
    			if(n2>n3) swap(n2,n3);
    			if(!n1)
    					insert(1,1,n,n2,n3);
    			if(n1)
    				printf("%lld
    ",query(1,1,n,n2,n3));
    		}puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    cookie操作
    css加载动画...
    三目运算符的运用
    遍历对象长度
    2年
    相亲

    股市周期
    功利心
    思考笔记
  • 原文地址:https://www.cnblogs.com/648-233/p/12912619.html
Copyright © 2011-2022 走看看