hdu4348(主席樹區間修改)

Problem - 4348 (hdu.edu.cn)
Background
To The Moon是一款獨立遊戲,於2011年11月發佈,是一款由RPG Maker提供支持的角色扮演冒險遊戲。
《去月球》的前提是基於一種技術,該技術使我們能夠永久地重建垂死之人的記憶。在這個問題上,我們將給你一個機會,實現幕後的邏輯。

您已經獲得了 N 個整數 A[1]、A[2],..., A[N]。在這些整數上,您需要實現以下操作:
1. C l r d:爲每個 {Ai | l <= i <= r} 添加一個常量 d,並將時間戳增加 1,這是唯一會導致時間戳增加的操作。
2. Q l r:查詢 {Ai | l <= i <= r} 的當前和。
3. H l r t:查詢時間 t.4
中 {Ai | l <= i <= r} 的歷史總和。B t:回到時間 t。一旦你決定回到過去,你就再也無法訪問前期版本了。
..N, M ≤ 105, |答[i]|≤ 109, 1 ≤ l ≤ r ≤ N, |d|≤ 104 ..系統從時間 0 開始,第一次修改是在時間 1 t≥ 0,並且不會將您引入未來狀態。

輸入

n m
A1 A2 ...一個n
...(此處遵循 M 操作。

輸出

...(對於每個查詢,只需打印結果即可。

思路

使用主席樹處理版本控制。由於涉及到區間修改,考慮使用懶標記,在區間更新的時候順帶求出區間和,避免傳遞懶標記可以節省時間,實測500多ms跑完。

  1 #define IO std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
  2 #define bug(x) cout<<#x<<" is "<<x<<endl
  3 #include <iostream>
  4 #include <list>
  5 #include <unordered_map>
  6 #include <map>
  7 #include <vector>
  8 #include <sstream>
  9 #include <cmath>
 10 #include <algorithm>
 11 #define iter ::iterator
 12 using namespace  std;
 13 typedef long long ll;
 14 typedef pair<int,int>P;
 15 #define pb push_back
 16 #define mk make_pair
 17 #define se second
 18 #define fi first
 19 const ll mod=1e9+7;
 20 const int N=1e5+5;
 21 int n,q;
 22 int a[N],rt[N*25],ls[N*25],rs[N*25];
 23 ll sum[N*25],add[N*25];
 24 int cnt;
 25 void build(int &o,int l,int r){
 26     o=++cnt;
 27     if(l==r){
 28         sum[o]=a[l];
 29         return;
 30     }
 31     int m=(l+r)/2;
 32     build(ls[o],l,m);
 33     build(rs[o],m+1,r);
 34     sum[o]=sum[ls[o]]+sum[rs[o]];
 35 }
 36 void up(int &o,int pre,int l,int r,int ql,int qr,int val){
 37     o=++cnt;
 38     ls[o]=ls[pre];
 39     rs[o]=rs[pre];
 40     add[o]=add[pre];
 41     sum[o]=sum[pre]+1ll*val*(min(r,qr)-max(l,ql)+1);
 42     if(l>=ql&&r<=qr){
 43         add[o]+=val;
 44         return;
 45     }
 46     int m=(l+r)/2;
 47     if(ql<=m)up(ls[o],ls[pre],l,m,ql,qr,val);
 48     if(qr>m)up(rs[o],rs[pre],m+1,r,ql,qr,val);
 49 
 50 }
 51 ll qu(int o,int l,int r,int ql,int qr){
 52     if(l>=ql&&r<=qr)return sum[o];
 53     ll res=add[o]*(min(r,qr)-max(l,ql)+1);
 54     int m=(l+r)/2;
 55     if(ql<=m)res+=qu(ls[o],l,m,ql,qr);
 56     if(qr>m)res+=qu(rs[o],m+1,r,ql,qr);
 57     return res;
 58 }
 59 int main(){
 60     while(~scanf("%d%d",&n,&q)){
 61         for(int i=1;i<=n;i++)scanf("%d",&a[i]);
 62         cnt=0;
 63         build(rt[0],1,n);
 64         int time=0;
 65         while(q--){
 66             char op;
 67             int L,R,val;
 68             scanf(" %c",&op);
 69             if(op=='Q'){
 70                 scanf("%d%d",&L,&R);
 71                 ll ans=qu(rt[time],1,n,L,R);
 72                 printf("%lld\n",ans);
 73             }
 74             else if(op=='C'){
 75                 scanf("%d%d%d",&L,&R,&val);
 76                 ++time;
 77                 up(rt[time],rt[time-1],1,n,L,R,val);
 78                 
 79             }
 80             else if(op=='H'){
 81                 scanf("%d%d%d",&L,&R,&val);
 82                 ll ans=qu(rt[val],1,n,L,R);
 83                 printf("%lld\n",ans);
 84             }
 85             else{
 86                 scanf("%d",&val);
 87                 time=val;
 88             }
 89         }
 90         printf("\n");
 91     }
 92 
 93 }
 94 /*
 95 10 100
 96 1 2 3 4 5 6 7 8 9 10
 97 Q 1 10
 98 C 3 6 3
 99 Q 1 10
100 Q 4 4
101 Q 1 10
102 Q 2 4
103 C 3 6 3
104 Q 2 4
105 */

 

 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章