To the moon
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2423 Accepted Submission(s): 480
Problem Description
Background
To The Moon is a independent game released in November 2011, it is a role-playing adventure game powered by RPG Maker.
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.
You‘ve been given N integers A [1], A [2],..., A [N]. On these integers, you need to implement the following operations:
1. C l r d: Adding a constant d for every {A i | l <= i <= r}, and increase the time stamp by 1, this is the only operation that will cause the time stamp increase.
2. Q l r: Querying the current sum of {A i | l <= i <= r}.
3. H l r t: Querying a history sum of {A i | l <= i <= r} in time t.
4. 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.
To The Moon is a independent game released in November 2011, it is a role-playing adventure game powered by RPG Maker.
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.
You‘ve been given N integers A [1], A [2],..., A [N]. On these integers, you need to implement the following operations:
1. C l r d: Adding a constant d for every {A i | l <= i <= r}, and increase the time stamp by 1, this is the only operation that will cause the time stamp increase.
2. Q l r: Querying the current sum of {A i | l <= i <= r}.
3. H l r t: Querying a history sum of {A i | l <= i <= r} in time t.
4. 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
A 1 A 2 ... A n
... (here following the m operations. )
A 1 A 2 ... A n
... (here following the m operations. )
Output
... (for each query, simply print the result. )
Sample Input
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 2 4 0 0 C 1 1 1 C 2 2 -1 Q 1 2 H 1 2 1
Sample Output
4 55 9 15 0 1
Author
HIT
Source
2012 Multi-University Training Contest 5
/*
今天学到了一种函数式线段树成段更新时节约内存的办法。
先考虑朴素的仅支持成段加减的线段树,我们可以用方式解决:
1.正常的懒惰标记,当访问到带有懒惰标记节点的子区间时将标记下传;
2.不用下传的懒惰标记,我们用一个标记来记录当前节点的整段区间被累加了多少,
当询问的时候我们在从根节点走到目标结点的过程中不断累加所经过节点上的标记值。
查询历史状态,在线做的话就要用可持久化数据结构,所谓可持久化,意思就是保存
所有的历史状态,但是因为每次修改只涉及到logn个节点,所以每次只新建logn个节点。
其余节点可利用历史版本的。*/
#include<stdio.h>
#define N 3000000//开大点
typedef long long ll;
int num,rson[N],lson[N],t[N];
ll sum[N],add[N];
int build(int x,int y)
{
int root=++num;
add[root]=0;
if(x==y)
{
lson[root]=rson[root]=0;
scanf("%I64d",&sum[root]);
return root;
}
int mid=(x+y)>>1;
lson[root]=build(x,mid);
rson[root]=build(mid+1,y);
sum[root]=sum[lson[root]]+sum[rson[root]];
return root;
}
void cop(int now,int root)
{
lson[now]=lson[root];
rson[now]=rson[root];
add[now]=add[root];
sum[now]=sum[root];
}
int update(int root,int l,int r,int x,int y,int k)
{
int now=++num;
cop(now,root);
if(l==x&&r==y)
{
add[now]+=k;
return now;
}
sum[now]+=(ll)(r-l+1)*k;
int mid=(x+y)>>1;
if(r<=mid)
lson[now]=update(lson[now],l,r,x,mid,k);
else if(l>mid)
rson[now]=update(rson[now],l,r,mid+1,y,k);
else
{
lson[now]=update(lson[now],l,mid,x,mid,k);
rson[now]=update(rson[now],mid+1,r,mid+1,y,k);
}
return now;
}
ll query(int root,int l,int r,int x,int y)
{
ll ans=add[root]*(r-l+1);
if(l==x&&r==y)
{
return (ans+sum[root]);
}
int mid=(x+y)>>1;
if(r<=mid)
ans+=query(lson[root],l,r,x,mid);
else if(l>mid)
ans+=query(rson[root],l,r,mid+1,y);
else
{
ans+=query(lson[root],l,mid,x,mid);
ans+=query(rson[root],mid+1,r,mid+1,y);
}
return ans;
}
int main()
{
int n,m,now,i,l,r,T,d;
char str[10];
// freopen("a.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF)
{
num=0; now=0;
t[0]=build(1,n);
for(i=1;i<=m;i++)
{
scanf("%s",str);
if(str[0]=='Q')
{
scanf("%d%d",&l,&r);
printf("%I64d\n",query(t[now],l,r,1,n));
}
else if(str[0]=='C')
{
scanf("%d%d%d",&l,&r,&d);
t[now+1]=update(t[now],l,r,1,n,d);
now++;
}
else if(str[0]=='H')
{
scanf("%d%d%d",&l,&r,&T);
printf("%I64d\n",query(t[T],l,r,1,n));
}
else
{
scanf("%d",&now);
}
}
}
return 0;
}