#10128. 「一本通 4.3 练习 2」花神游历各国

版权声明:转载请标明出处 https://blog.csdn.net/kumu28/article/details/89052663

#10128. 「一本通 4.3 练习 2」花神游历各国(题目链接)

大意:区间开根号,询问区间和

laz 标记区间是否全为 0,1

扩展 % 运算是最坏为 n/2的

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+500;
#define ll long long
#define ls rt<<1,l,mid
#define rs rt<<1|1,mid+1,r
ll tre[maxn<<2],laz[maxn<<2];
int n,m;
ll mp[maxn];
void build(int rt,int l,int r){
    laz[rt] = 0;
    if(l==r){
        tre[rt] = mp[l];
        if(tre[rt]==1||tre[rt]==0) laz[rt]=1;
        return ;
    }
    int mid = l+r>>1;
    build(ls);build(rs);
    tre[rt]=tre[rt<<1]+tre[rt<<1|1];
    if(laz[rt<<1]&&laz[rt<<1|1]) laz[rt]=1;
}
ll qur(int rt,int l,int r,int a,int b){
    if(l>=a&&r<=b) return tre[rt];
    int mid = l+r>>1;
    ll an=0;
    if(a<=mid) an+=qur(ls,a,b);
    if(b>mid) an+=qur(rs,a,b);
    return an;
}
void upda(int rt,int l,int r,int a,int b){
    if(laz[rt]==1)return ;
    if(l==r){
        tre[rt] = (ll)sqrt(tre[rt]);
        if(tre[rt]==1||tre[rt]==0) laz[rt]=1;
        return ;
    }
    int mid = l+r>>1;
    if(a<=mid) upda(ls,a,b);
    if(b>mid) upda(rs,a,b);
    tre[rt]=tre[rt<<1]+tre[rt<<1|1];
    if(laz[rt<<1]&&laz[rt<<1|1]) laz[rt]=1;//0 1都不用再开
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%lld",&mp[i]);
    build(1,1,n);
    scanf("%d",&m);
    int a,b,c;
    for(int i=0;i<m;++i){
        scanf("%d%d%d",&a,&b,&c);
        if(b>c) swap(b,c);
        if(a-1){
            upda(1,1,n,b,c);
        }
        else{
            printf("%lld\n",qur(1,1,n,b,c));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/kumu28/article/details/89052663