P4145 上帝造题的七分钟2 / 花神游历各国

P4145 上帝造题的七分钟2 / 花神游历各国

线段树

区间开方线段树

其实也可以分块写

不管数有多大,那么开方若干次后一定是0/1,这时就无需继续开方,有一个tag标记维护即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef ll arr[400002];
template <typename T> inline void read(T &x){
    char c=getchar(); x=0;
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
}
int n,m; arr sum,tag;
inline void build(int o,int l,int r){
    if(l==r) {read(sum[o]); return;}
    int lc=o<<1,rc=o<<1|1,mid=l+((r-l)>>1);
    build(lc,l,mid); build(rc,mid+1,r);
    sum[o]=sum[lc]+sum[rc];
}
int x1,x2;
inline void _sqrt(int o,int l,int r){
    if(tag[o]) return ;
    if(l==r){
        sum[o]=sqrt(sum[o]);
        if(sum[o]<2) tag[o]=1;
        return;
    }
    int lc=o<<1,rc=o<<1|1,mid=l+((r-l)>>1);
    if(x1<=mid) _sqrt(lc,l,mid);
    if(x2>mid) _sqrt(rc,mid+1,r);
    sum[o]=sum[lc]+sum[rc];
    tag[o]=tag[lc]&tag[rc]; //如果本区间都无需开方
}
inline ll query(int o,int l,int r){
    if(x1<=l&&r<=x2) return sum[o];
    ll ans=0;
    int lc=o<<1,rc=o<<1|1,mid=l+((r-l)>>1);
    if(x1<=mid) ans+=query(lc,l,mid);
    if(x2>mid) ans+=query(rc,mid+1,r);
    return ans;
}
int main(){
    read(n); build(1,1,n);
    read(m); int opt;
    for(int i=1;i<=m;++i){
        read(opt); read(x1); read(x2);
        if(x1>x2) swap(x1,x2);
        if(opt==0) _sqrt(1,1,n);
        else printf("%lld\n",query(1,1,n));
    }return 0;
}

 

转载于:https://www.cnblogs.com/kafuuchino/p/9695043.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值