Hdu 5828 Rikka with Sequence

区间每一个数开根
区间加x
区间求和


线段树,具体见代码

#include<bits/stdc++.h>
using namespace std;

#define LL long long

struct Info{
    LL same,siz,sum;
    Info(LL x = 0){
        same = sum = x;
        siz = x!=0;
    }
    void add(LL x){
        sum += siz * x;
        if(same != -1) same += x;
    }
    void sqr(){
        same = (LL)sqrt(same * 1.0);
        sum = same * siz;
    }   
    void set(LL x){
        same = x;
        sum = siz * x;
    }
};

Info operator + (const Info & L,const Info & R){
    Info ret;
    if(L.same == R.same) ret.same = L.same;
    else ret.same = -1;
    ret.siz = L.siz + R.siz;
    ret.sum = L.sum + R.sum;
    return ret;
}

#define root 1,1,n
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define Now int o,int l,int r
#define Mid int m = (l + r) / 2

const int maxn = 112345;
LL arr[maxn];
int n;
Info info[maxn*4];
LL lazy[maxn*4];

void seter(int o,LL v){
    lazy[o] += v;
    info[o].add(v);
}

void push_down(Now){
    if(l != r){
        if(info[o].same != -1){
            info[o<<1].set(info[o].same);
            info[o<<1|1].set(info[o].same);
            lazy[o<<1] = lazy[o<<1|1] = 0;
            lazy[o] = 0;
        }
        if(lazy[o]){
            seter(o<<1,lazy[o]);
            seter(o<<1|1,lazy[o]);
        }
    }
    lazy[o] = 0;
}

void add(Now,int ul,int ur,LL v){
    if(ul <= l && r <= ur){
        info[o].add(v);
        lazy[o] += v;
        return;
    }
    Mid;
    if(lazy[o] || info[o].same != -1) push_down(o,l,r);
    if(ul <= m) add(lson,ul,ur,v);
    if(m+1<=ur) add(rson,ul,ur,v);
    info[o] = info[o<<1] + info[o<<1|1];
}

void sqrt(Now,int ul,int ur){
    if(ul <= l && r <= ur && info[o].same != -1){
        info[o].sqr();
        return;
    }
    Mid;
    if(lazy[o] || info[o].same != -1) push_down(o,l,r);
    if(ul <= m) sqrt(lson,ul,ur);
    if(m+1<=ur) sqrt(rson,ul,ur);
    info[o] = info[o<<1] + info[o<<1|1];
}

Info query(Now,int ql,int qr){
    if(ql <= l && r <= qr){
        return info[o];
    }
    Mid;
    if(lazy[o] || info[o].same != -1) push_down(o,l,r);
    Info ret;
    if(ql <= m) ret = ret + query(lson,ql,qr);
    if(m+1<=qr) ret = ret + query(rson,ql,qr);
    return ret;
}

void build(Now){
    if(l != r){
        Mid;
        build(lson),build(rson);
        info[o] = info[o<<1] + info[o<<1|1];
    }
    else{
        info[o] = Info(arr[l]);
    }
}
int main(){
    int T;
    scanf("%d",&T);
    int n,m;
    while(T-- && ~scanf("%d %d",&n,&m)){
        for(int i=1;i<=n;i++){
            scanf("%I64d",&arr[i]);
        }
        build(root);
        memset(lazy,0,sizeof(lazy));
        int ord,l,r;
        LL x;
        while(m--){
            scanf("%d %d %d",&ord,&l,&r);
            if(ord == 1){
                scanf("%I64d",&x);
                add(root,l,r,x);
            }
            if(ord == 2) sqrt(root,l,r);
            if(ord == 3) printf("%I64d\n",query(root,l,r).sum);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值