BZOJ3038 上帝造题的七分钟2 线段树

一个数最多是会被开方次数不会很多,所以直接暴力修改即可. 

#include <bits/stdc++.h>  
#define N 100005 
#define ll long long  
#define lson now<<1
#define rson now<<1|1 
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) 
using namespace std;  
int n,m,tag[N<<2]; 
ll A[N],sum[N<<2];       
void build(int l,int r,int now) 
{
    if(l==r) 
    {
        sum[now]=A[l]; 
        if(sum[now]==1ll) tag[now]=1;      
        return; 
    }
    int mid=(l+r)>>1;   
    if(l<=mid) build(l,mid,lson); 
    if(r>mid)  build(mid+1,r,rson);    
    sum[now]=sum[lson]+sum[rson];  
    if(sum[now]==r-l+1) tag[now]=1;      
} 
ll query(int l,int r,int now,int L,int R) 
{
    if(l>=L&&r<=R) return sum[now]; 
    int mid=(l+r)>>1; 
    ll re=0; 
    if(L<=mid) re+=query(l,mid,lson,L,R); 
    if(R>mid)  re+=query(mid+1,r,rson,L,R); 
    return re; 
} 
void update(int l,int r,int now,int L,int R) 
{
    if(tag[now]) return ; 
    if(l==r) 
    {
        sum[now]=(ll)sqrt(sum[now]);  
        return; 
    } 
    int mid=(l+r)>>1;  
    if(L<=mid) update(l,mid,lson,L,R); 
    if(R>mid)  update(mid+1,r,rson,L,R);     
    sum[now]=sum[lson]+sum[rson]; 
    if(sum[now]==r-l+1) tag[now]=1;  
}
int main() 
{  
    int i,j; 
    // setIO("input");  
    scanf("%d",&n);  
    for(i=1;i<=n;++i) scanf("%lld",&A[i]);     
    build(1,n,1);       
    scanf("%d",&m); 
    for(i=1;i<=m;++i) 
    {
        int op,l,r; 
        scanf("%d%d%d",&op,&l,&r); 
        if(l>r) swap(l,r);  
        if(op==1) 
        {
            printf("%lld\n",query(1,n,1,l,r)); 
        } 
        else
        {
            update(1,n,1,l,r); 
        }
    }
    return 0; 
}

  

posted @ 2019-09-28 14:39  EM-LGH  阅读(124)  评论(0编辑  收藏  举报