您的位置:首页 > 其它

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

2017-07-14 11:22 567 查看


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.


Description

You‘ve been given N integers A[1], A[2],..., A
. 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: