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

by luogu

可用于练习线段树

这里涉及到了开方操作

和 +   * 不同,它的运算次数大大减小

只有大概8次操作就会到1

而1无论开多少次的方

都是1

所以可以去掉懒标了

这里的mark所记录的是区间最大值

若最大值都为1,那么也就吗,没有必要再进行计算

但是修改的话

还是需要一次到底(l==r)

这次就懒得打注释了QAQ

#include<bits/stdc++.h>

#define int long long
#define mid ((l+r)>>1)
using namespace std;

int c[400011];
int a[400011],mark[400011];

void build(int x,int l,int r)
{
    if(l==r)
    {
        a[x]=c[l];
        mark[x]=c[l];
        return ;
    }
    
    build((x<<1),l,mid);
    build((x<<1)|1,mid+1,r);
    
    a[x]=a[x<<1]+a[(x<<1)|1];
    mark[x]=max(mark[x<<1],mark[(x<<1)|1]);
    
    return ;
}


void pl(int x,int l,int r,int s,int e)
{
    if(s>r||e<l)
    return ; 
    if(l==r)
    {
    a[x]=sqrt(a[x]);
        mark[x]=a[x];
        
        return ;
    }
//    push(x,l,r);
    if(mark[x<<1]>1&&mid>=s)
        pl((x<<1),l,mid,s,e);
        
    if(mark[(x<<1)|1]>1&&mid<e)
    pl((x<<1)|1,mid+1,r,s,e);
        
        
    a[x]=a[x<<1]+a[(x<<1)|1];
    mark[x]=max(mark[x<<1],mark[(x<<1)|1]);
    

    
    return ; 
}

int query(int x,int l,int r,int s,int e)
{
    if(s>r||e<l) 
    return 0; 
    if(s<=l&&r<=e) 
    return a[x];
    
    //push(x,l,r);
    return query((x<<1),l,mid,s,e)+query((x<<1)+1,mid+1,r,s,e);  
}

int n,m;

signed main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
    cin>>c[i];
    
    build(1,1,n);    
    cin>>m;
    
    for(int i=1;i<=m;i++)
    {
        int q,w,e;
        cin>>q>>w>>e;
        if(w>e)
        swap(w,e);
        if(q)
        cout<<query(1,1,n,w,e)<<endl;

        else
            pl(1,1,n,w,e);
            
                
                
        
    }
    
    return 0;    
}
上一篇:SP2 PRIME1 - Prime Generator,解题未遂的欧拉筛法,改用经典优化素数算法


下一篇:从 Synchronized 到锁的优化