大概内容是要维护一个数组,支持如下操作:
查询某个位置上的数
修改某个位置上的数
回到某个版本的数组(可持久化)
预备知识:平衡树(非必要,了解最好),主席树
为了维护这个结构,我们可以考虑使用主席树,
建树的时候按照下标来建(维护下标),此处类似于平衡树
要查询指定位置就按照找第k大,同样类似于平衡树。
这样的话对于任意版本的线段树,我们实际上是在按照下标维护一个数列,
这样修改某个位置的数就是相当于线段树的单点修改,
跟主席树的常规操作是一样的,很好理解
附一个很妙的建树方法:
十分妙的建树方法???
因为线段树的传统建树是十分平衡的,而线段树理论上要用到2n-1个点,
其中n个节点是叶节点,而上面的都是区间,由于每个区间都不同,
所以他们的mid也两两不同,why?
感性的理解,在root的时候,mid是最中间的,
然后往左走,因为r减小,l不变,所以mid会向左移,
同理,往右走的时候,mid会向右移,
因此这满足一个性质,一个点左边的mid都小于它的mid,一个点右边的mid都大于它的mid,
因为它右边的l最小也是mid+1了,所以一个点右边的mid都大于它的mid,
又因为它左边的r最大也是mid,在不取叶节点的情况下,由于mid会偏向左,
因此左边的mid再大也不可能到达上面的mid那么大,
由于对于所有节点都满足这个性质(有点类似于平衡树了),
所以这些点的mid都是两两不同的,
但是注意到线段树的非叶节点只有n-1个,所以还少了一个点。而这个点必然是mid=n的点,
同样注意到对于一个区间而言,mid会偏向左,因此只要是一个区间,mid永远不可能到达n,
所以要补上n,n这个叶节点
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define AC 1030100 5 #define ac 20000100 6 #define D printf("line in %d ",__LINE__); 7 #define getchar() *o++ 8 char READ[55001000],*o=READ; 9 int n,m,tot=1,who,ans,change; 10 int root[AC],s[AC]; 11 struct Segament_Tree{ 12 int date,lson,rson,mid; 13 }tree[ac]; 14 inline int read() 15 { 16 int x=0;char c=getchar();bool z=false; 17 while(c > '9' || c < '0') 18 { 19 if(c == '-') z=true; 20 c=getchar(); 21 } 22 while(c >= '0' && c <= '9') x=x*10+c-'0',c=getchar(); 23 if(!z) return x; 24 else return -x; 25 } 26 27 void build(int x,int l,int r)//尽量平衡的建树 28 { 29 int mid=(l + r) >> 1; 30 tree[x].date=s[mid]; 31 tree[x].mid=mid; 32 if(l == r) return ; 33 if(r - l == 1) 34 { 35 if(r != n) return ; 36 else 37 { 38 tree[x].rson=++tot; 39 build(tot,r,r); 40 } 41 } 42 else 43 { 44 tree[x].lson=++tot; 45 build(tot,l,mid); 46 tree[x].rson=++tot; 47 build(tot,mid+1,r); 48 } 49 } 50 51 void pre() 52 { 53 n=read(),m=read(); 54 for(R i=1;i<=n;i++) s[i]=read(); 55 root[0]=1; 56 } 57 58 void insert(int &now) 59 { 60 tree[++tot]=tree[now],now=tot;//建新节点 61 if(tree[now].mid == who)//如果已经对应到当前节点了 62 { 63 tree[now].date=change;//修改 64 return ; 65 } 66 else if(who < tree[now].mid) insert(tree[now].lson); 67 else insert(tree[now].rson); 68 } 69 70 void search(int x) 71 { 72 if(who < tree[x].mid) search(tree[x].lson); 73 else if(who > tree[x].mid) search(tree[x].rson); 74 else ans=tree[x].date; 75 } 76 77 void work() 78 { 79 int a,tmp; 80 for(R i=1;i<=m;i++) 81 { 82 tmp=read(),a=read(); 83 if(a == 1) 84 { 85 who=read(),change=read(); 86 root[i]=root[tmp]; 87 insert(root[i]); 88 } 89 else 90 { 91 who=read(); 92 root[i]=root[tmp];//error!!!是基于tmp的版本啊。。。。 93 search(root[tmp]); 94 printf("%d ",ans); 95 } 96 } 97 } 98 99 int main() 100 { 101 // freopen("in.in","r",stdin); 102 fread(READ,1,55000000,stdin); 103 pre(); 104 build(1,1,n); 105 work(); 106 //fclose(stdin); 107 return 0; 108 }