SPOJ TTM - To the moon (主席树,区间更新,区间查询)

Background

To The Moon is a independent game released in November 2011, it is a role-playing adventure game powered by RPG Maker.

River && Anya .. .

The premise of To The Moon is based around a technology that allows us to permanently reconstruct the memory on dying man. In this problem, we'll give you a chance, to implement the logic behind the scene.

Description

You‘ve been given N integers A[1], A[2],..., A[N]. On these integers, you need to implement the following operations:

  • C l r d: Adding a constant d for every {Ai | l <= i <= r}, and increase the timestamp by 1, this is the only operation that will cause the timestamp increase. 
  • Q l r: Querying the current sum of {Ai | l <= i <= r}.
  • H l r t: Querying a history sum of {Ai | l <= i <= r} in time t.
  • B t: Back to time t. And once you decide return to a past, you can never be access to a forward edition anymore.

 .. N, M ≤ 10^5, |A[i]| ≤ 10^9, 1 ≤ l ≤ r ≤ N, |d| ≤ 10^4 .. the system start from time 0, and the first modification is in time 1, t ≥ 0, and won't introduce you to a future state. 

Input

n m
A1 A2 ... An
... (here following the m operations. )

Output

... (for each query, simply print the result. )

Example

Input 1:
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4

Output 1:
4 55 9 15

Input 2:
2 4 0 0 C 1 1 1 C 2 2 -1 Q 1 2 H 1 2 1

Output 2:

0 1

题意:N个数,M次操作,操作1,区间 l~r +d 时间+1 操作2,询问此时的区间和,操作3,询问t时的区间和,操作4,此时时间变成 t 

主席树,对各个时间建线段树,用来查询区间和,需要注意的是延迟标记下沿时需要新建立2个节点,内存消耗过大,所以我们采用不下沿标记的方法,只需要在询问时将延迟标记和记录下来计算即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <queue>
#define mem(p,k) memset(p,k,sizeof(p));
#define rep(a,b,c) for(int a=b;a<c;a++)
#define pb push_back
//#define lson l,m,rt<<1
//#define rson m+1,r,rt<<1|1
#define inf 0x6fffffff
#define ll long long
using namespace std;
const int maxn=110005;
int n,m,tot,ti;
int h[maxn];
int lson[maxn*30],rson[maxn*30];
ll cur[maxn*30],sum[maxn*30];
void pushup(int now,int l,int r){
    sum[now]=sum[lson[now]]+sum[rson[now]]+cur[now]*(r-l+1);//*******这里注意容易错
}
void build(int &now,int l,int r){
    now=++tot;
    cur[now]=0;
    if(l==r){
        scanf("%lld",sum+now);
        return ;
    }
    int m=(l+r)>>1;
    build(lson[now],l,m);
    build(rson[now],m+1,r);
    pushup(now,l,r);

}
void update(int &now,int pre,int L,int R,int val,int l,int r){
    now=++tot;
    lson[now]=lson[pre];
    rson[now]=rson[pre];
    cur[now]=cur[pre];
    sum[now]=sum[pre];
    if(L<=l && r<=R){
        cur[now]+=val;
        sum[now]+=(r-l+1)*val;//cout<<l<<r<<"=="<<sum[now]<<endl;
        return;
    }
    int m=(l+r)>>1;
    if(m>=L)update(lson[now],lson[pre],L,R,val,l,m);
    if(m<R) update(rson[now],rson[pre],L,R,val,m+1,r);
    pushup(now,l,r);
}
ll query(int rt,int L,int R,int l,int r,ll val){
    if(L<=l && r<=R){
        return val*(r-l+1)+sum[rt];
    }
    val+=cur[rt];
    int m=(l+r)>>1;
    ll ret=0;
    if(m>=L)ret+=query(lson[rt],L,R,l,m,val);
    if(m<R) ret+=query(rson[rt],L,R,m+1,r,val);
    return ret;
}
int main(){

    while(~scanf("%d%d",&n,&m)){
        tot=0;
        ti=0;
        build(h[0],1,n);
        while(m--){
            int l,r,x;
            char s[2];
            scanf("%s",s);
            if(s[0]=='C'){
                scanf("%d%d%d",&l,&r,&x);
                update(h[ti+1],h[ti],l,r,x,1,n);
                ti++;
            }
            else if(s[0]=='Q'){
                scanf("%d%d",&l,&r);
                printf("%lld\n",query(h[ti],l,r,1,n,0));
            }
            else if(s[0]=='H'){
                scanf("%d%d%d",&l,&r,&x);
                printf("%lld\n",query(h[x],l,r,1,n,0));
            }
            else {
                scanf("%d",&x);
                ti=x;
            }
        }
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值