题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4348
题目链接:
时间倒流那肯定是主席树啊,然后区间修改要用永久标记.下传标记不能使用,空间会炸.
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int mx = 1e5 + 10;
int n,m,rs[30*mx],ls[30*mx];
int root[mx],tot,d;
ll sum[30*mx],add[mx*30];
void build(int l,int r,int& rt)
{
rt = tot++;
add[rt] = 0;
if(l==r){
scanf("%lld",sum+rt);
return ;
}
int mid = (l+r)>>1;
build(l,mid,ls[rt]);
build(mid+1,r,rs[rt]);
sum[rt] = sum[ls[rt]] + sum[rs[rt]];
}
void update(int x,int &y,int l,int r,int L,int R)
{
y = tot++;
rs[y] = rs[x],ls[y] = ls[x];
sum[y] = sum[x] + 1ll*(R-L+1)*d,add[y] = add[x];
if(L<=l&&r<=R){
add[y] += d;
return ;
}
int mid = (l+r)>>1;
if(R<=mid) update(ls[x],ls[y],l,mid,L,R);
else if(L>mid) update(rs[x],rs[y],mid+1,r,L,R);
else{
update(ls[x],ls[y],l,mid,L,mid);
update(rs[x],rs[y],mid+1,r,mid+1,R);
}
}
ll query(int rt,int l,int r,int L,int R,ll ad)
{
if(L<=l&&r<=R) return sum[rt] + (r-l+1)*ad;
int mid = (l+r)>>1;
ll ans = 0;
if(L<=mid) ans += query(ls[rt],l,mid,L,R,ad+add[rt]);
if(R>mid) ans += query(rs[rt],mid+1,r,L,R,ad+add[rt]);
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m)){
tot = 0;
build(1,n,root[0]);
char ch[5];
int time = 0,L,R,t;
while(m--){
scanf("%s",ch);
if(ch[0]=='C'){
scanf("%d%d%d",&L,&R,&d);
time++;
update(root[time-1],root[time],1,n,L,R);
}else if(ch[0]=='Q')
{
scanf("%d%d",&L,&R);
printf("%lld\n",query(root[time],1,n,L,R,0));
}else if(ch[0]=='H')
{
scanf("%d%d%d",&L,&R,&t);
printf("%lld\n",query(root[t],1,n,L,R,0));
}else if(ch[0]=='B'){
scanf("%d",&t);
time = t;
}else while(1);
}
}
return 0;
}