HDU 4383 To The Moon
题意翻译
已知一个长为\(n\)的序列\(a\),你需要进行下面的四种操作。
C l r d
将区间\([l,r]\)中的数加上\(d\),同时时间加\(1\)
Q l r
查询当前时间区间\([l,r]\)中所有数的和
H l r t
查询时间为\(t\)时区间\([l,r]\)中所有数的和
B t
将当前时间置为\(t\)
输入输出格式
输入格式
多组数据
每组数据第一行两个整数\(n,m\)
第二行\(n\)个整数,代表时间为\(0\)时的数列
后面\(m\)行,每行若干个整数,代表一次操作
输出格式
每一个查询操作输出一行作为答案
输入输出样例
输入样例#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 42 4
0 0
C 1 1 1
C 2 2 -1
Q 1 2
H 1 2 1
输出样例#1
4
55
9
150
1
说明
对于所有的数据有\(n,m\le 10^5,|a_i| \le 10^9\),\(|d|\le 10^4\),保证所有操作合法。
没什么可说的,就是标记永久化一下进行区间修改。
这方面的细节很多,以后需要多加注意。
Code:
#include <cstdio>
#include <cstring>
#define ll long long
const int N=1e5+10;
int ch[N*30][2],tot,root[N],n,m;
ll sum[N*30],tag[N*30],a[N];
#define ls ch[now][0]
#define rs ch[now][1]
void build(int &now,int l,int r)
{now=++tot;ls=rs=sum[now]=tag[now]=0;if(l==r){sum[now]=a[l];return;}int mid=l+r>>1;build(ls,l,mid),build(rs,mid+1,r);sum[now]=sum[ls]+sum[rs];
}
void change(int las,int &now,int L,int R,int l,int r,ll d)
{now=++tot;ls=ch[las][0],rs=ch[las][1];if(L==l&&R==r){tag[now]=tag[las]+d;sum[now]=sum[las]+d*(R+1-L);ls=ch[las][0],rs=ch[las][1];return;}int Mid=L+R>>1;if(r<=Mid) change(ch[las][0],ls,L,Mid,l,r,d);else if(l>Mid) change(ch[las][1],rs,Mid+1,R,l,r,d);else change(ch[las][0],ls,L,Mid,l,Mid,d),change(ch[las][1],rs,Mid+1,R,Mid+1,r,d);tag[now]=tag[las];sum[now]=sum[ls]+sum[rs]+tag[now]*(R+1-L);
}
ll query(int now,int L,int R,int l,int r)
{if(!now||now>tot) return 0;if(l==L&&r==R) return sum[now];int Mid=L+R>>1;ll delta=tag[now]*(r+1-l);if(r<=Mid) return query(ls,L,Mid,l,r)+delta;else if(l>Mid) return query(rs,Mid+1,R,l,r)+delta;else return query(ls,L,Mid,l,Mid)+query(rs,Mid+1,R,Mid+1,r)+delta;
}
void work()
{tot=0;int t=0;for(int i=1;i<=n;i++) scanf("%lld",a+i);build(root[0],1,n);char op[4];ll d;for(int l,r,k,i=1;i<=m;i++){scanf("%s",op);if(op[0]=='C'){scanf("%d%d%lld",&l,&r,&d);++t;change(root[t-1],root[t],1,n,l,r,d);}else if(op[0]=='Q'||op[0]=='H'){scanf("%d%d",&l,&r);if(op[0]=='Q') k=t;else scanf("%d",&k);printf("%lld\n",query(root[k],1,n,l,r));}elsescanf("%d",&t),tot=root[t+1]-1;}
}
int main()
{while(scanf("%d%d",&n,&m)!=EOF) work();return 0;
}
2018.12.2