可持久化数据结构是为了保存这个数据结构的所有历史版本
正文
这是一棵非常好看的线段树
考虑一个问题,现在修改6号节点,同时保留原始信息,怎么做
重构一棵线段树,该修改的就修改,其余信息复制
显然不对因为我们在说可持久化而不是重构
遵从不浪费原则,我们要尽可能多的利用不需要修改的节点
根据线段树的知识,我们知道修改一个点的同时也会影响他的父亲及祖先
所以标星的点是要被修改的
我们把要修改的点重建,保留不需要修改的就变成了介个样子
同时我们还要充分利用旧的线段树,那怎么办呢
直接把他指过去就行了
由于1的左子树和3的右儿子是全部不用修改,所以直接指过去是可以维护的
(不带修)静态查询区间第k大(小)
// // main.cpp // 【模版】可持久化线段树(主席树) // // Created by gengyf on 2019/7/12. // Copyright © 2019 yifan Geng. All rights reserved. // #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define mid (l+r)/2 using namespace std; const int N = 200010; int n, q, m, cnt = 0; int a[N], b[N], T[N]; int sum[N<<5], L[N<<5], R[N<<5]; inline int build(int l, int r){ int rt = ++ cnt; sum[rt] = 0; if (l < r){ L[rt] = build(l, mid); R[rt] = build(mid+1, r); } return rt; } inline int update(int pre, int l, int r, int x){ int rt = ++ cnt; L[rt] = L[pre]; R[rt] = R[pre]; sum[rt] = sum[pre]+1; if (l < r){ if (x <= mid) L[rt] = update(L[pre], l, mid, x); else R[rt] = update(R[pre], mid+1, r, x); } return rt; } inline int query(int u, int v, int l, int r, int k){ if (l >= r) return l; int x = sum[L[v]] - sum[L[u]]; if (x >= k) return query(L[u], L[v], l, mid, k); else return query(R[u], R[v], mid+1, r, k-x); } int main(){ scanf("%d%d", &n, &q); for (int i = 1; i <= n; i ++){ scanf("%d", &a[i]); b[i] = a[i]; } sort(b+1, b+1+n); m = unique(b+1, b+1+n)-b-1; T[0] = build(1, m); for (int i = 1; i <= n; i ++){ int t = lower_bound(b+1, b+1+m, a[i])-b; T[i] = update(T[i-1], 1, m, t); } while (q --){ int x, y, z; scanf("%d%d%d", &x, &y, &z); int t = query(T[x-1], T[y], 1, m, z); printf("%d ", b[t]); } return 0; }
(带修)动态区间第k大(小)洛谷P2617
1 // 2 // main.cpp 3 // 【模版】动态区间第k大(树状数组主席树) 4 // 5 // Created by gengyf on 2019/9/1. 6 // Copyright © 2019 yifan Geng. All rights reserved. 7 // 8 9 #include <iostream> 10 using namespace std; 11 namespace gengyf{ 12 const int N=5e5+1; 13 struct ls{ 14 int w,num; 15 }pp[N<<1];//离散化 16 struct que{ 17 char ss[3]; 18 int l,r,k; 19 }q[N];//询问 20 struct tree{ 21 int w,l,r; 22 }t[N<<5]; 23 inline bool cmp(ls x,ls y){ 24 return x.w<y.w; 25 } 26 int root[N]; 27 int pas[N],now[N],L,R; 28 int e,ran,sz,a[N<<1],s[N];//离散化数组大小,排名个数,排名数组,原值数组 29 inline void lisan(){//离散化 30 sort(pp+1,pp+e+1,cmp); 31 a[pp[1].num]=ran=1; 32 s[1]=pp[1].w; 33 for(int i=2;i<=e;i++){ 34 if(pp[i].w!=pp[i-1].w){ 35 s[++ran]=pp[i].w; 36 } 37 a[pp[i].num]=ran; 38 } 39 } 40 inline int lowbit(int x){ 41 return x&-x; 42 } 43 inline void add(int &now,int l,int r,int x){//新建 44 if(!now){ 45 now=++sz; 46 } 47 t[now].w++; 48 if(l==r){ 49 return ; 50 } 51 int mid=(l+r)>>1; 52 if(x<=mid)add(t[now].l,l,mid,x); 53 else add(t[now].r,mid+1,r,x); 54 } 55 inline void del(int now,int l,int r,int x){//删除 56 t[now].w--; 57 if(l==r){ 58 return ; 59 } 60 int mid=(l+r)>>1; 61 if(x<=mid){ 62 del(t[now].l,l,mid,x); 63 return ; 64 } 65 del(t[now].r,mid+1,r,x); 66 } 67 inline int kth(int l,int r,int k){//查询 68 if(l==r){ 69 return l; 70 } 71 int sum=0; 72 for(int i=1;i<=L;i++){ 73 sum-=t[t[pas[i]].l].w; 74 } 75 for(int i=1;i<=R;i++){ 76 sum+=t[t[now[i]].l].w; 77 } 78 int mid=(l+r)>>1; 79 if(sum>=k){ 80 for(int i=1;i<=L;i++){ 81 pas[i]=t[pas[i]].l; 82 } 83 for(int i=1;i<=R;i++){ 84 now[i]=t[now[i]].l; 85 } 86 return kth(l,mid,k); 87 } 88 for(int i=1;i<=L;i++){ 89 pas[i]=t[pas[i]].r; 90 } 91 for(int i=1;i<=R;i++){ 92 now[i]=t[now[i]].r; 93 } 94 return kth(mid+1,r,k-sum); 95 } 96 int n,m; 97 int main(){ 98 scanf("%d%d",&n,&m); 99 for(int i=1;i<=n;i++){ 100 scanf("%d",&pp[i].w); 101 pp[i].num=i; 102 } 103 e=n; 104 for(int i=1;i<=m;i++){ 105 scanf("%s%d%d",&q[i].ss,&q[i].l,&q[i].r); 106 if(q[i].ss[0]=='Q'){ 107 scanf("%d",&q[i].k); 108 } 109 else { 110 e++; 111 pp[e].w=q[i].r;pp[e].num=n+i; 112 } 113 } 114 lisan(); 115 for(int i=1;i<=n;i++){ 116 int x=i; 117 while(x<=n){ 118 add(root[x],1,ran,a[i]); 119 x+=lowbit(x); 120 } 121 } 122 for(int i=1;i<=m;i++){ 123 if(q[i].ss[0]=='Q'){ 124 L=R=0; 125 int Now=q[i].l-1; 126 while(Now){ 127 pas[++L]=root[Now]; 128 Now-=lowbit(Now); 129 } 130 Now=q[i].r; 131 while(Now){ 132 now[++R]=root[Now]; 133 Now-=lowbit(Now); 134 } 135 printf("%d ",s[kth(1,ran,q[i].k)]); 136 } 137 else { 138 int Now=q[i].l; 139 while(Now<=n){ 140 del(root[Now],1,ran,a[q[i].l]); 141 Now+=lowbit(Now); 142 } 143 Now=q[i].l; 144 while(Now<=n){ 145 add(root[Now],1,ran,a[i+n]); 146 Now+=lowbit(Now); 147 } 148 a[q[i].l]=a[i+n]; 149 continue; 150 } 151 } 152 return 0; 153 } 154 } 155 int main() { 156 gengyf::main(); 157 return 0; 158 }
ps:目前只放了代码,会补解释的QwQ(咕咕咕~