P3919 【模板】可持久化数组(可持久化线段树/平衡树)
可持久化线段树
不过我对与这一道题有一个想法:
有没有一种可持久化的数组?
带着类似于可持久化线段树的新建节点的想法,我画下了图:
偶们得到了一个初始数组!
接下来修改:pos 1 val 14
那么我们这么做:
这样其实我们就可以On修改On查询了!
(那么优秀的O(n)算法,怎么能不爆踩呢)
思考了一下,这个东西好像可以分块,类似这样:
修改都在块内进行,维护一下,可以On√n?
没实现,那位大佬发表一下集训队论文吧
接下来说正经的:
这道题就是一个裸的可持久化线段树
具体网上学
记住这题的ask操作也要生成一个版本,生成一个和他ask版本一毛一样的版本!
(我正纳闷:哪来10个版本!)
代码:
#include<bits/stdc++.h> using namespace std; const int N=1000005; struct node{ int l; int r; int lson; int rson; int val; }; int n,m; int a[N]; struct Sugment_Tree{ #define mid (l+r)/2 #define il inline int root[N]; node t[N<<4]; int cnt;//线段树节点数 int times;//几次版本 Sugment_Tree(){cnt=0,times=0;memset(root,0,sizeof(root));} il int build(int l,int r){ if(l==r){ cnt++; t[cnt].val=a[l]; t[cnt].lson=-1; t[cnt].rson=-1; t[cnt].l=l; t[cnt].r=r; return cnt; } cnt++; int y=cnt; t[y].lson=build(l,mid); t[y].rson=build(mid+1,r); t[y].val=0; t[y].l=l; t[y].r=r; return y; } il int upt(node u,int pos,int X){ if(u.l==u.r&&u.r==pos){ cnt++; t[cnt]=u; t[cnt].val=X; return cnt; } cnt++; int y=cnt; t[y]=u; node l=t[u.lson],r=t[u.rson]; if(l.l<=pos&&l.r>=pos){ t[y].lson=upt(l,pos,X); t[y].rson=u.rson; } if(r.l<=pos&&r.r>=pos){ t[y].rson=upt(r,pos,X); t[y].lson=u.lson; } return y; } il int serch(node u,int pos){ if(u.l==u.r&&u.r==pos){ return u.val; } node l=t[u.lson],r=t[u.rson]; if(l.l<=pos&&l.r>=pos){ return serch(l,pos); } if(r.l<=pos&&r.r>=pos){ return serch(r,pos); } return -10; } }T; int main(){ freopen("a.in","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); T.times++; T.root[1]=T.build(1,n); while(m--){ int a,b,c,d; scanf("%d%d%d",&a,&b,&c); a++; if(b==1){ scanf("%d",&d); T.times++; T.root[T.times]=T.upt(T.t[T.root[a]],c,d); } else{ printf("%d\n",T.serch(T.t[T.root[a]],c)); T.times++; T.root[T.times]=T.root[a]; } } return 0; }