hdu4348 To the moon,函数式线段树
修改某个区间,求某个区间的和,求某个区间过去某个时间的和,回到过去某个时间。
这是函数式线段树的裸题了。
修改区间可以将区间的变化量保存在对应区间的节点上,这样就不用lazy了。lazy还会导致更多的空间消耗。
修改某个区间,求某个区间的和,求某个区间过去某个时间的和,回到过去某个时间。
这是函数式线段树的裸题了。
修改区间可以将区间的变化量保存在对应区间的节点上,这样就不用lazy了。lazy还会导致更多的空间消耗。
由于卡空间,我只好把线段树写成了不保存左右端点的形式(不符合我风格啊)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define NN 100010
struct segtree{
int ls,rs,d;
long long tot;
void init(){
ls=rs=d=0;
tot=0;
}
long long gettot(long long sz){
return tot+sz*d;
}
}t[NN*24];
int tott,root[NN];
int val[NN];
int build(int l,int r){
int p=++tott;
t[p].d=0;
if (l==r){
t[p].ls=t[p].rs=0;t[p].tot=val[l];return p;
}
int m=(l+r)>>1;
t[p].ls=build(l,m);
t[p].rs=build(m+1,r);
t[p].tot=t[t[p].ls].tot+t[t[p].rs].tot;
return p;
}
int update(int l,int r,int tl,int tr,int pas,int num){
int p=++tott;
t[p]=t[pas];
if (tl==l&&tr==r){
t[p].d+=num;
return p;
}
int m=tl+tr>>1;
if (r<=m) t[p].ls=update(l,r,tl,m,t[p].ls,num);
else if (l>m) t[p].rs=update(l,r,m+1,tr,t[p].rs,num);
else{
t[p].ls=update(l,m,tl,m,t[p].ls,num);
t[p].rs=update(m+1,r,m+1,tr,t[p].rs,num);
}
t[p].tot=t[t[p].ls].gettot(m+1-tl)+t[t[p].rs].gettot(tr-m);
return p;
}
long long query(int l,int r,int tl,int tr,int p){
if (tl==l&&tr==r){
return t[p].gettot(tr+1-tl);
}
int m=tl+tr>>1;
long long tmp=((long long)r+1-l)*t[p].d;
if (r<=m) return query(l,r,tl,m,t[p].ls)+tmp;
else if (l>m) return query(l,r,m+1,tr,t[p].rs)+tmp;
else {
return query(l,m,tl,m,t[p].ls)+query(m+1,r,m+1,tr,t[p].rs)+tmp;
}
}
int main(){
//freopen("4348in.txt","r",stdin);
int n,m,i,tim,a,b,c;
char s[10];
while(scanf("%d%d",&n,&m)!=EOF){
for(i=1;i<=n;++i){
scanf("%d",&val[i]);
}
tott=0;
t[0].init();
root[0]=build(1,n);
tim=0;
for(i=1;i<=m;++i){
scanf("%s",s);
if (s[0]=='C'){
scanf("%d%d%d",&a,&b,&c);
root[tim+1]=update(a,b,1,n,root[tim],c);
tim++;
}
else if (s[0]=='Q'){
scanf("%d%d",&a,&b);
printf("%I64d\n",query(a,b,1,n,root[tim]));
}
else if (s[0]=='H'){
scanf("%d%d%d",&a,&b,&c);
printf("%I64d\n",query(a,b,1,n,root[c]));
}
else if (s[0]=='B'){
scanf("%d",&a);
tim=a;
}
}
}
return 0;
}