hdu4348 To the moon 区间更新

题目:给你N个数,M个操作,操作有4种类型,C l r d 将区间[l,r]加上d,Q l r 询问区间[l,r]的和,H l r t询问时间t的区间[l,r]的和,B t回到时间t,初始时时间是0,每进行一次C操作,时间加1

思路:主席树,注意lazy标记下传会产生大量的空间,内存不够,因此lazy直接放在节点上就好了,查询的时候加上去就行了

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define PI acos(-1.0)
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
// 0x3f3f3f3f


const int maxn=1e5+50;
const int maxm=maxn*30;
int root[maxn],lson[maxm],rson[maxm],lazy[maxm];
LL sum[maxm];
int tot;
int arr[maxn];
int build(int l,int r){
    int rt=tot++;
    lazy[rt]=0;
    if(l==r){
        sum[rt]=arr[l];
        return rt;
    }
    int mid=(l+r)/2;
    lson[rt]=build(l,mid);
    rson[rt]=build(mid+1,r);
    sum[rt]=sum[lson[rt]]+sum[rson[rt]];
    return rt;
}
int update(int rt,int l,int r,int L,int R,int val){
    int newrt=tot++;
    lazy[newrt]=lazy[rt];
    if(L<=l&&r<=R){
        lazy[newrt]+=val;
        sum[newrt]=sum[rt]+(LL)(r-l+1)*val;
        lson[newrt]=lson[rt];
        rson[newrt]=rson[rt];
        return newrt;
    }
    int mid=(l+r)/2;
    if(R<=mid){
        lson[newrt]=update(lson[rt],l,mid,L,R,val);
        rson[newrt]=rson[rt];
    }
    else if(L>mid){
        lson[newrt]=lson[rt];
        rson[newrt]=update(rson[rt],mid+1,r,L,R,val);
    }
    else{
        lson[newrt]=update(lson[rt],l,mid,L,R,val);
        rson[newrt]=update(rson[rt],mid+1,r,L,R,val);
    }
    sum[newrt]=sum[lson[newrt]]+sum[rson[newrt]]+(LL)lazy[newrt]*(r-l+1);
    return newrt;
}
LL ans;
void query(int rt,int l,int r,int L,int R,int val){
    if(L<=l&&r<=R){
        ans+=sum[rt]+(LL)val*(r-l+1);
        return;
    }
    int mid=(l+r)/2;
    if(L<=mid) query(lson[rt],l,mid,L,R,val+lazy[rt]);
    if(R>mid) query(rson[rt],mid+1,r,L,R,val+lazy[rt]);
}
int main(){

    int n,m,l,r,d,t;
    char str[20];
    while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=n;i++)
            scanf("%d",&arr[i]);
        int now=0;
        tot=0;
        root[now]=build(1,n);
        while(m--){
            scanf("%s",str);
            if(str[0]=='C'){
                scanf("%d%d%d",&l,&r,&d);
                now++;
                root[now]=update(root[now-1],1,n,l,r,d);
            }
            else if(str[0]=='Q'){
                scanf("%d%d",&l,&r);
                ans=0;
                query(root[now],1,n,l,r,0);
                printf("%lld\n",ans);
            }
            else if(str[0]=='H'){
                scanf("%d%d%d",&l,&r,&d);
                ans=0;
                query(root[d],1,n,l,r,0);
                printf("%lld\n",ans);
            }
            else{
                scanf("%d",&t);
                now=t;
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值