hdu 4348 To the moon (带标记主席树)

题意:

思路:

    每次修改,就新开一个树,如果大小是l到r包含叶子节点的一颗树自然是不可以的,那么我们只能保存包含他们的上面的节点,并且lazy也要同步更新(这一步和线段树很类似),但是,我们并不能pushdown,因为pushdown会直接导致空间炸掉。
    那么我们为了能够用到lazy,那么我们就可以将路径上的lazy加起来,最后和区间大小相乘,就是正确的最终结果

错误及反思:

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m
#define rson m+1,r
const int N = 100100;
long long sum[N*30];
int ls[N*30],rs[N*30],root[N],arr[N],lazy[N*30];
int n,q,cnt,t;

int build(int l,int r){
    int rt=++cnt;
    sum[rt]=arr[l];ls[rt]=rt;rs[rt]=rt;lazy[rt]=0;
    if(l==r) return rt;
    int m=l+r>>1;
    ls[rt]=build(lson); rs[rt]=build(rson);
    sum[rt]=sum[ls[rt]]+sum[rs[rt]];
    return rt;
}

int update(int pre,int L,int R,int val,int l,int r){
    int rt=++cnt;
    sum[rt]=sum[pre];ls[rt]=ls[pre];rs[rt]=rs[pre];lazy[rt]=lazy[pre];
    if(L<=l&&R>=r) {lazy[rt]+=val;sum[rt]+=1ll*(r-l+1)*val; return rt;}
    int m=l+r>>1;
    if(m>=L) ls[rt]=update(ls[pre],L,R,val,lson);
    if(m<R) rs[rt]=update(rs[pre],L,R,val,rson);
    sum[rt]=sum[ls[rt]]+sum[rs[rt]]+1ll*lazy[rt]*(r-l+1);
    return rt;
}

long long query(int tim,int L,int R,int l,int r,long long tp){
    if(L<=l&&R>=r) return sum[tim]+tp*(r-l+1);
    int m=(l+r)/2;
    long long ans=0;
    if(m>=L) ans+=query(ls[tim],L,R,lson,tp+lazy[tim]);
    if(m<R) ans+=query(rs[tim],L,R,rson,tp+lazy[tim]);
    return ans;
}

int main(){
    while(scanf("%d%d",&n,&q)!=EOF){
        cnt=1; t=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&arr[i]);
        root[0]=build(1,n);
        while(q--){
            char ta[10];
            scanf("%s",ta);
            if(ta[0]=='Q'){
                int l,r; scanf("%d%d",&l,&r);
                printf("%lld\n",query(root[t],l,r,1,n,0));
            }
            else if(ta[0]=='C'){
                int l,r,d; scanf("%d%d%d",&l,&r,&d);
                root[t+1]=update(root[t],l,r,d,1,n);
                t++;
            }
            else if(ta[0]=='H'){
                int l,r,tb; scanf("%d%d%d",&l,&r,&tb);
                printf("%lld\n",query(root[tb],l,r,1,n,0));
            }
            else{
                int tb; scanf("%d",&tb);
                if(t!=tb){t=tb; cnt=root[t+1]-1;}
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Roll_Keyboard/article/details/80560176
今日推荐