zoukankan      html  css  js  c++  java
  • SP2713 GSS4

    「题意」: n 个数,和在10^18 范围内。n<=1e5

    现在有「两种」操作

    0 x y把区间[x,y] 内的每个数开方,下取整

    1 x y询问区间[x,y] 的每个数的和

    和平常的线段树一样,只不过多了一个开方,拿计算器算一下,发现1e18开了大概6次后就会变为1,以后在开方就没用了,所以可以直接跳过这个区间

    具体来说,维护一个区间的最大值,在每次执行‘ 0 ' 操作时,单点修改,若发现此区间最大值<=1,则不进入此区间,这样可以降低许多复杂度.

    Code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define ll long long
    using namespace std;
    int n,m,T;
    ll a[100010];
    struct Node{
        int l,r;ll dat,sum;
        #define l(p) t[p].l
        #define r(p) t[p].r
        #define sum(p) t[p].sum
    }t[100010*4];
    inline ll read(){
        char c=getchar();ll x=0,flag=1;
        while(c<'0' || c>'9'){if(c=='-') flag=-1;c=getchar();}
        while(c>='0' && c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
        return x*flag;
    }
    void build(int p,int l,int r){
        t[p].l=l;t[p].r=r;
        if(l==r){t[p].dat=t[p].sum=a[l];return;}
        int mid=(l+r)>>1;build(p*2,l,mid);build(p*2+1,mid+1,r);
        t[p].dat=max(t[p*2].dat,t[p*2+1].dat);t[p].sum=t[p*2].sum+t[p*2+1].sum;
    }
    void change(int p,int l,int r){
        if(l(p)==r(p)){t[p].dat=sqrt(t[p].dat);t[p].sum=t[p].dat;return;}
        int mid=(l(p)+r(p))>>1;
        if(l<=mid && t[p*2].dat>1) change(p*2,l,r);
        if(r>mid && t[p*2+1].dat>1) change(p*2+1,l,r);
        t[p].dat=max(t[p*2].dat,t[p*2+1].dat);t[p].sum=t[p*2].sum+t[p*2+1].sum;  
    }
    ll ask(int p,int l,int r){
        if(l<=l(p) && r>=r(p)) return sum(p);
        int mid=(l(p)+r(p))>>1;ll val=0;
        if(l<=mid) val+=ask(p*2,l,r);if(r>mid) val+=ask(p*2+1,l,r);
        return val;
    }
    int main(){
        while(scanf("%d",&n) != EOF){
            printf("Case #%d:
    ",++T);
            memset(&t,0,sizeof(t));
            for(int i=1;i<=n;i++) a[i]=read();
            build(1,1,n);m=read();
            while(m--){
                int num,x,y;num=read();x=read();y=read();
                if(!num) change(1,min(x,y),max(x,y));
                else printf("%lld
    ",ask(1,min(x,y),max(x,y)));
            }
            printf("
    ");
        }
    }
  • 相关阅读:
    填坑!!!virtualenv 中 nginx + uwsgi 部署 django
    树的遍历与递归
    Python 函数的参数
    virtualbox安装增强功能时【未能加载虚拟光盘】
    深入理解Python中的生成器
    Genymotion下载慢或者下载失败的解决办法
    Python3 多线程的两种实现方式
    Java 多线程
    关于"裁员与面试"的个人感悟吧
    三、由简单对象组装复杂实例的模式:建造者模式
  • 原文地址:https://www.cnblogs.com/SyhAKIOI/p/11675612.html
Copyright © 2011-2022 走看看