HDU 4383 To The Moon 解題報告
阿新 • • 發佈:2018-12-02
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 4
2 4
0 0
C 1 1 1
C 2 2 -1
Q 1 2
H 1 2 1
輸出樣例#1
4
55
9
15
0
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)); } else scanf("%d",&t),tot=root[t+1]-1; } } int main() { while(scanf("%d%d",&n,&m)!=EOF) work(); return 0; }
2018.12.2