• HDU 5828 Rikka with Sequence(线段树)


    【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5828

     

    【题目大意】

      给出一个数列,要求支持区间加法,区间开方和区间和查询操作。

    【题解】

      考虑开方后会出现成片相同的数字,因此我们在每个区间额外维护区间内数字是否相同的tag,如果区间内数字均相同,那么开方就可以转化为减法的标记,即t=sqrt(t)转化为tag=sqrt(t)-t。剩下就是简单的标记维护了。

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <cmath> 
    using namespace std; 
    const int N=2000000;
    struct node{int l,r,f,a,b;long long tag,max,val;}T[N];
    int cas,tot,n,m,l,r,c,op,num;
    void addtag(int x,int tag){
        T[x].tag+=tag;
        T[x].max+=tag;
        T[x].val+=(long long)tag*(T[x].b-T[x].a+1);
    }
    void pb(int x){
        if(T[x].l){addtag(T[x].l,T[x].tag);addtag(T[x].r,T[x].tag);}
        T[x].tag=0;
    }
    void up(int x){
        T[x].max=max(T[T[x].l].max,T[T[x].r].max);
        T[x].val=T[T[x].l].val+T[T[x].r].val;
        if(T[T[x].l].f&&T[T[x].r].f&&T[T[x].l].max==T[T[x].r].max)T[x].f=1;
        else T[x].f=0;
    }
    void build(int l,int r){
        int x=++tot;
        T[x].a=l;T[x].b=r;T[x].f=0;
        T[x].tag=T[x].l=T[x].r=T[x].max=T[x].val=0;
        if(l==r){T[x].f=1;scanf("%lld",&T[x].val);T[x].max=T[x].val;return;}
        int mid=(l+r)>>1;
        T[x].l=tot+1;build(l,mid);
        T[x].r=tot+1;build(mid+1,r);
        up(x);
    }
    void change(int x,int a,int b,int p){
        if(T[x].a>=a&&T[x].b<=b){addtag(x,p);return;}
        if(T[x].tag)pb(x); int mid=(T[x].a+T[x].b)>>1;
        if(mid>=a&&T[x].l)change(T[x].l,a,b,p);
        if(mid<b&&T[x].r)change(T[x].r,a,b,p);up(x);
    }
    long long query_sum(int x,int a,int b){
        if(T[x].a>=a&&T[x].b<=b)return T[x].val;
        if(T[x].tag)pb(x);int mid=(T[x].a+T[x].b)>>1;long long res=0;
        if(mid>=a&&T[x].l)res+=query_sum(T[x].l,a,b);
        if(mid<b&&T[x].r)res+=query_sum(T[x].r,a,b); 
        return res;
    }
    void Tsqrt(int x,int a,int b){
        if(T[x].a>=a&&T[x].b<=b){
            if(T[x].f){
                long long t=T[x].max;
                t=sqrt(t);
                addtag(x,t-T[x].max);
                return;
            }
        }if(T[x].tag)pb(x); int mid=(T[x].a+T[x].b)>>1;
        if(mid>=a&&T[x].l)Tsqrt(T[x].l,a,b);
        if(mid<b&&T[x].r)Tsqrt(T[x].r,a,b);up(x);
    }
    int main(){
        scanf("%d",&cas);
        while(cas--){
            scanf("%d%d",&n,&m);
            build(1,n);tot=0;
            while(m--){
                scanf("%d",&op);
                if(op==1){
                    scanf("%d%d%d",&l,&r,&num);
                    change(1,l,r,num);
                }else if(op==2){
                    scanf("%d%d",&l,&r);
                    Tsqrt(1,l,r);
                }else{
                    scanf("%d%d",&l,&r);
                    printf("%lld
    ",query_sum(1,l,r));
                }
            }
        }return 0;
    }
    

      

  • 相关阅读:
    Java常用类之【日期相关类】
    Java常用类之【Math类、Random类、System类、Runtime类】
    Java常用类之【字符串相关类型】
    Java常用类之【八种基本数据类型】
    打印杨辉三角--for循环
    Eclipse设置文字大小
    Eclipse之JSON导包
    Java中设计模式之工厂模式-4
    PC 微信页面倒计时代码 safari不兼容date的问题
    在apache中设置访问目录后进入的默认页面为index.php
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu5828.html
Copyright © 2020-2023  润新知