To the moon
题目链接: To the moon HDU - 4348
题意
给你长度为n的数组,共有四个操作:
•1.对区间【L,R】增加d,并时间增加1
•2.询问当前时间的区间【L,R】的和
•3.询问时间为T时的区间【L,R】的和
•4.返回到时间为T的时候
思路
既然有着时间点的要求也就是历史版本的要求,那么主席树肯定是没跑的了,奈何我没有合适的模板,那么这道题,就是我主席树的模板了吧。还有但是主席树的区间的修改,一种办法是在遇到有延迟更新的区间的时候重新开左右儿子来pushdown 标记,但是这题严格一点的数据就能把他卡成空间为n*n*logn。所以还有一种办法就是,永久化标记,不pushdown,这时候就可以大大节省空间了,nlogn的空间复杂度。
代码
#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
typedef double db;
typedef long long ll;
const int MAXN = (int)1e5+7;
const int INF = (int)0x3f3f3f3f;
int root[MAXN*10],lc[MAXN*32],rc[MAXN*32],tot;
ll tree[MAXN*32],add[MAXN*32];
int A[MAXN];
void Build(int l,int r,int root){
add[root] = 0;
if(l == r) {
tree[root] = A[l];
return ;
}
int mid = l+r>>1;
Build(l,mid,lc[root]=++tot);
Build(mid+1,r,rc[root]=++tot);
tree[root] = tree[lc[root]] + tree[rc[root]];
}
void Update(int last,int cur,int L,int R,int l,int r,ll d){
tree[cur] = tree[last] + d*(min(R,r)-max(L,l)+1);
lc[cur] = lc[last];
rc[cur] = rc[last];
add[cur] = add[last];
if(L <= l && r <= R) {
add[cur] += d;
return ;
}
int mid = l+r>>1;
if (L <= mid)Update(lc[last],lc[cur]=++tot,L,R,l,mid,d);
if (R > mid)Update(rc[last],rc[cur]=++tot,L,R,mid+1,r,d);
}
ll query(int cur,int L,int R,int l,int r,ll ad){
if(L <= l && r <= R) return tree[cur]+(r-l+1)*ad;
int mid = l+r>>1;
ll ans = 0;
if (L <= mid)ans += query(lc[cur],L,R,l,mid,ad+add[cur]);
if (R > mid)ans += query(rc[cur],L,R,mid+1,r,ad+add[cur]);
return ans;
}
void init() {
tot = 0;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)){
init();
rep(i,1,n) scanf("%lld",&A[i]);
Build(1,n,root[1]=++tot);
int time = 1;
rep(i,1,m) {
char op[2];int l,r,t;ll k;
scanf("%s",op);
if(op[0] == 'C') {
scanf("%d %d %lld",&l,&r,&k);
time++;
Update(root[time-1],root[time]=++tot,l,r,1,n,k);
}
else if(op[0]=='Q') {
scanf("%d %d",&l,&r);
printf("%lld\n",query(root[time],l,r,1,n,0));
}
else if(op[0]=='H') {
scanf("%d %d %d",&l,&r,&t);
t++;
printf("%lld\n",query(root[t],l,r,1,n,0));
}
else if(op[0]=='B') {
scanf("%d",&t);
time=t+1;
}
}
}
}