hdu 4348 - 區間修改主席樹
阿新 • • 發佈:2018-10-31
題目連結: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; }