SPOJ
这就没有什么好缩的了,板子题一道,只不过用了标记永久化的思想,就比较方便一些咯
#include
#define pushup(x) sum[x]=sum[lc[x]]+sum[rc[x]]
using namespace std;
typedef long long ll;
const int maxn=100010,maxm=10000010;
int n,m,tot,now,rt[maxn],lc[maxm],rc[maxm];
ll sum[maxm],add[maxm];
char op[5];
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return xvoid build(int l,int r,int &rt)
{
rt=++tot;
if(l==r){read(sum[rt]);return ;}
int m=(l+r)>>1;
build(l,m,lc[rt]);
build(m+1,r,rc[rt]);
pushup(rt);
}
void update(int l,int r,int L,int R,int val,int &rt)
{
++tot;lc[tot]=lc[rt];rc[tot]=rc[rt];
add[tot]=add[rt];sum[tot]=sum[rt];rt=tot;
if(L<=l&&r<=R){add[rt]+=val;return ;}
sum[rt]+=(ll)val*(min(R,r)-max(L,l)+1);
int m=(l+r)>>1;
if(L<=m) update(l,m,L,R,val,lc[rt]);
if(m1,r,L,R,val,rc[rt]);
}
ll query(int l,int r,int L,int R,int rt)
{
ll res=(ll)add[rt]*(min(R,r)-max(L,l)+1);
if(L<=l&&r<=R) return sum[rt]+res;
int m=(l+r)>>1;
if(L<=m) res+=query(l,m,L,R,lc[rt]);
if(m1,r,L,R,rc[rt]);
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int x,y,d;
read(n);read(m);
build(1,n,rt[0]);
while(m--)
{
scanf("%s",op);
if(op[0]=='Q'){read(x);read(y);printf("%lld\n",query(1,n,x,y,rt[now]));}
else if(op[0]=='C')
{
read(x);read(y);read(d);
rt[now+1]=rt[now];now++;
update(1,n,x,y,d,rt[now]);
}
else if(op[0]=='H')
{
read(x);read(y);read(d);
printf("%lld\n",query(1,n,x,y,rt[d]));
}
else if(op[0]=='B') read(now),tot=rt[now+1]-1;
}
return 0;
}