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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

可持续化线段树

發布時間:2024/9/5 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 可持续化线段树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
可持續化線段樹,也叫主席樹,很久以前【也沒多久】寫了一篇求區間第k大的,那時候理解不深,現在再寫一個加深理解
可持續化,具體來說就是可以訪問歷史版本,以實現跨時間的操作。
怎么實現呢? 試想我們修改線段樹的時候,修改前是舊版本,修改后是新版本,想想新版本和舊版本有什么區別? 區別就在于從根節點到被修改點的路徑上的點改變了,其他的點是不變的
那么這個時候我們新建一個根節點,對于不變的兒子指向舊版本的兒子,對于有變化的兒子就新建一個節點 這樣一來我們有每一個時刻的根節點,就可以訪問到每個時刻的線段樹 空間會不會暴呢? 每條路徑只有logn個點,m次修改我們只多了mlogn個點,可以承受 但實在空間卡得很緊時就要用指針了
比如洛谷P3931
下面給出指針版題解代碼【并非完全是普遍的寫法,由題簡化】: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long int #define REP(i,n) for (int i = 1; i <= (n); i++) #define fo(i,x,y) for (int i = (x); i <= (y); i++) #define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next) using namespace std; const int maxn = 1000005,maxm = 10000005,INF = 1000000000;inline int read(){int out = 0,flag = 1;char c = getchar();while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}return out * flag; }int N,M,A[maxn];struct node{int v;node *ls,*rs;node() {ls = rs = NULL;} }; node* rt[maxn]; int rti = 0,pos;void Build(node **u,int l,int r){*u = new node;if (l == r){(*u)->v = A[l];}else {int mid = l + r >> 1;Build(&(*u)->ls,l,mid);Build(&(*u)->rs,mid + 1,r);} }void change(node *pre,node **u,int l,int r,int v){(*u) = new node;*(*u) = *pre;if (l == r){(*u)->v = v;}else {int mid = l + r >> 1;if (mid >= pos) change(pre->ls,&(*u)->ls,l,mid,v);else change(pre->rs,&(*u)->rs,mid + 1,r,v);} }int Query(node *u,int l,int r){if (l == r) return u->v;else {int mid = l + r >> 1;if (mid >= pos) return Query(u->ls,l,mid);else return Query(u->rs,mid + 1,r);} }int main() {N = read();M = read();REP(i,N) A[i] = read();Build(&rt[0],1,N);int pre,cmd,v;while (M--){pre = read();cmd = read();pos = read();if (cmd & 1){v = read();change(rt[pre],&rt[++rti],1,N,v);}else {printf("%d\n",Query(rt[++rti] = rt[pre],1,N));}}return 0; }

轉載于:https://www.cnblogs.com/Mychael/p/8282846.html

總結

以上是生活随笔為你收集整理的可持续化线段树的全部內容,希望文章能夠幫你解決所遇到的問題。

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