题目链接:To the moon
题意:给个数组,三种操作,第一种询问当前区间[l,r]的和,第二种给区间[l,r]的每一个数加上d,第三种询问在第几次修改后[l,r]的权值
题解:如果这题只询问区间和更新,简单建棵线段树维护区间和用延时标记就可以了,但是它询问第几次修改之后一段区间的值,这样的话刚才的方法就不好用,那我们可不可以,在每次修改之后的重新建一棵线段树呢?直接重新建的话空间会爆,这个时候就可以用??币的主席树(没学过主席树可以先做一下这个),每次的修改只会再新增logN个节点,先把给的数组,建好第一棵主席树(建的时候把add数组初始化为0),然后要然后之后的每次更新根据前面的主席树,只要新增(log(n)个节点)。然后询问的时候,用对应的主席树询问区间和就可以了。
1 #include<bits/stdc++.h> 2 #include<set> 3 #include<cstdio> 4 #include<iomanip> 5 #include<iostream> 6 #include<string> 7 #include<cstring> 8 #include<algorithm> 9 #define pb push_back 10 #define ll long long 11 #define PI 3.14159265 12 //#define ls l,m,rt<<1 13 //#define rs m+1,r,rt<<1|1 14 #define eps 1e-7 15 typedef unsigned long long ull; 16 const int mod=1e9+9; 17 const ll inf=0x3f3f3f3f3f3f3f; 18 const int maxn=1e5+5; 19 const int N=1e4+7; 20 using namespace std; 21 int n,m,ls[maxn*30],rs[maxn*30],rt[maxn],t,tot; 22 ll sum[maxn*30],add[maxn*30]; 23 char op[5]; 24 void built(int &o,int l,int r) 25 { 26 o=++tot; 27 sum[o]=0;add[o]=0; 28 if(l==r) 29 { 30 scanf("%lld",&sum[o]);return ; 31 } 32 int m=(l+r)>>1; 33 built(ls[o],l,m); 34 built(rs[o],m+1,r); 35 sum[o]=sum[ls[o]]+sum[rs[o]]; 36 } 37 void up(int rt,int l,int r) 38 { 39 int m=(l+r)>>1; 40 sum[rt]=sum[ls[rt]]+sum[rs[rt]]+add[ls[rt]]*(m-l+1)+add[rs[rt]]*(r-m); 41 } 42 int update(int root,int l,int r,int L,int R,int val) 43 { 44 int newroot=++tot; 45 add[newroot]=add[root]; 46 if(L<=l&&r<=R) 47 { 48 ls[newroot]=ls[root]; 49 rs[newroot]=rs[root]; 50 sum[newroot]=sum[root]; 51 add[newroot]=add[root]+val; 52 return newroot; 53 } 54 int m=(l+r)>>1; 55 if(L<=m)ls[newroot]=update(ls[root],l,m,L,R,val); 56 else ls[newroot]=ls[root]; 57 if(R>m)rs[newroot]=update(rs[root],m+1,r,L,R,val); 58 else rs[newroot]=rs[root]; 59 up(newroot,l,r); 60 return newroot; 61 } 62 ll query(int rt,int l,int r,int L,int R,ll val) 63 { 64 if(L<=l&&r<=R) 65 { 66 return sum[rt]+1ll*(add[rt]+val)*(r-l+1); 67 } 68 int m=(l+r)>>1; 69 ll ans=0; 70 if(L<=m)ans+=query(ls[rt],l,m,L,R,val+add[rt]); 71 if(R>m)ans+=query(rs[rt],m+1,r,L,R,val+add[rt]); 72 return ans; 73 } 74 int main() 75 { 76 int l,r,val,T; 77 while(~scanf("%d %d",&n,&m)) 78 { 79 tot=0;t=0; 80 built(rt[0],1,n); 81 while(m--) 82 { 83 scanf("%s",op); 84 if(op[0]==‘Q‘) 85 { 86 scanf("%d %d",&l,&r); 87 printf("%lld\n",query(rt[t],1,n,l,r,0)); 88 } 89 else if(op[0]==‘C‘) 90 { 91 92 scanf("%d %d %d",&l,&r,&val); 93 rt[t+1]=update(rt[t],1,n,l,r,val); 94 t++; 95 } 96 else if(op[0]==‘H‘) 97 { 98 scanf("%d %d %d",&l,&r,&T); 99 printf("%lld\n",query(rt[T],1,n,l,r,0)); 100 } 101 else 102 { 103 scanf("%d",&T); 104 tot=rt[T+1]; 105 t=T; 106 } 107 } 108 } 109 return 0; 110 }
HDU - 4348 To the moon(主席树区间更新)
原文:https://www.cnblogs.com/lhclqslove/p/8782635.html