SPOJ TTM

来源:互联网 发布:java red5搭建直播 编辑:程序博客网 时间:2024/06/06 01:55

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 51 2 3 4 5 6 7 8 9 10Q 4 4Q 1 10Q 2 4C 3 6 3Q 2 4

Output 1:
455915

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

Output 2:

01

题意: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 longusing 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;}