日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU - 4348 To the moon(主席树区间更新-标记永久化)

發布時間:2024/4/11 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU - 4348 To the moon(主席树区间更新-标记永久化) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個初始時長度為 n 的序列,有 m 次操作,每種操作分為下列四種類型:

  • C l r d:新建一個繼承了前一個版本的數組,并將區間 [ l , r ] 內的數字都加上 d
  • Q l r:訪問最后一個版本的數組,[ l , r ] 內的區間和
  • H l r t:訪問第 t 個版本的數組,[ l , r ] 內的區間和
  • B t:回溯到第 t 個版本
  • 題目分析:如果不考慮變量 t ,也就是不同版本的數組所帶來的影響,那么這就是線段樹的一道經典區間修改和區間查詢的題目,寫一個 lazy 下傳標記即可

    考慮有多個不同版本的數組,也就對應了主席樹,換句話說這個題目考察的正是主席樹的區間修改和區間查詢

    主席樹的單點修改比較簡單,每次只會涉及到一條鏈,即 logn 條節點,直接新建,其余的節點繼承上一個位置的即可

    區間修改的話如果考慮 lazy 變量的下傳,最壞的情況下需要從根節點下傳到葉子節點,一次操作的時空復雜度都是 nlogn 級別的

    那可能有的同學會說了:我就先存一下 lazy 標記,等查詢的時候再下傳不就行了?

    很遺憾的說,這樣的時間復雜度單次操作也將會是 nlogn 級別的,因為不同版本的線段樹可能 lazy 標記不同,導致 nlogn 個節點的值最終都不相同,所以都需要新建才行

    所以這里需要引入一個新的概念,也就是線段樹的標記永久化

    對于普通線段樹的 lazy 標記下傳操作,也就是 pushdown 函數,對應過去就是:線段樹中每個節點的值都是真實的值

    但標記永久化顧名思義,也就是 lazy 標記不下傳,這樣線段樹中的每個節點對應的值此時并不是真實的值,但在執行 query 操作時,一定會從其父節點下來,此時額外維護一個變量,用于記錄沿途路徑上的 lazy 的貢獻,最后統一計算一樣可以得到真實答案

    但在執行標記永久化時需要注意的細節就是,不能使用 pushup 函數自底向上去傳遞貢獻,只能自頂向下去維護每個節點的貢獻,到達需要返回的位置時,打一個 lazy 標記直接返回即可,這樣的操作帶來的影響是:相應的區間上面的父節點中儲存的是真實值,而 lazy 標記下面的那些節點中存在的都是一個虛擬的值,需要與祖先節點中的 lazy 標記的貢獻進行加和才能得到真實答案

    使用標記永久化的一個好處就是,每次修改仍然是至多修改 logn 個節點,這樣就能實現主席樹的區間修改的操作了

    對于這個題目而言,注意一下空間大小,因為初始時需要建立一棵線段樹,這里需要 4 * n ,然后每次修改都需要新建 logn 條樹鏈,設 n 與 m 同階,最終需要新建 nlogn 個樹鏈,總的空間復雜度也就是 n ( 4 + nlogn ),logn 記為 20,所以開 25 * n 就好了

    代碼:

    //#pragma GCC optimize(2) //#pragma GCC optimize("Ofast","inline","-ffast-math") //#pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;struct Node {int l,r;LL sum,lazy; }tree[N*25];int cnt,root[N];void build(int &k,int l,int r) {k=cnt++;tree[k].lazy=0;if(l==r){scanf("%lld",&tree[k].sum);return;}int mid=l+r>>1;build(tree[k].l,l,mid);build(tree[k].r,mid+1,r);tree[k].sum=tree[tree[k].l].sum+tree[tree[k].r].sum; }void update(int &k,int l,int r,int L,int R,LL val)//[l,r]:目標區間 [L,R]:當前區間 {tree[cnt++]=tree[k];k=cnt-1;tree[k].sum+=val*(r-l+1);if(L>=l&&R<=r){tree[k].lazy+=val;return;}int mid=L+R>>1;if(r<=mid)update(tree[k].l,l,r,L,mid,val);else if(l>mid)update(tree[k].r,l,r,mid+1,R,val);else{update(tree[k].l,l,mid,L,mid,val);update(tree[k].r,mid+1,r,mid+1,R,val);} }LL query(int k,int l,int r,int L,int R,LL add)//[l,r]:目標區間 [L,R]:當前區間 {if(R<l||L>r)return 0;if(L>=l&&R<=r)return tree[k].sum+add*(R-L+1);int mid=L+R>>1;return query(tree[k].l,l,r,L,mid,add+tree[k].lazy)+query(tree[k].r,l,r,mid+1,R,add+tree[k].lazy); }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n,m;while(scanf("%d%d",&n,&m)!=EOF){cnt=1;build(root[0],1,n);int time=0;while(m--){char op[5];scanf("%s",op);if(op[0]=='C'){int l,r,d;scanf("%d%d%d",&l,&r,&d);time++;root[time]=root[time-1];update(root[time],l,r,1,n,d);}else if(op[0]=='Q'){int l,r;scanf("%d%d",&l,&r);printf("%lld\n",query(root[time],l,r,1,n,0));}else if(op[0]=='H'){int l,r,t;scanf("%d%d%d",&l,&r,&t);printf("%lld\n",query(root[t],l,r,1,n,0));}else if(op[0]=='B'){scanf("%d",&time);}}}return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的HDU - 4348 To the moon(主席树区间更新-标记永久化)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。