洛谷 P3919 【模板】可持久化数组(可持久化线段树/平衡树)

当然是可以用可持久化线段树/平衡树做的。不过这里记一下一种奇怪的方法:http://blog.csdn.net/kscla/article/details/53586880

如果用线段树来维护的话,线段树上非叶子节点的节点都是没有用的,因为并不需要它们记录值。因此可以建一棵二叉树,每一个节点表示原数组上一个位置,节点1表示数组的第一个元素,之后的节点满足:设节点i表示数组的第k个元素,则节点i的左子节点表示数组的第k*2个元素,右子节点表示数组的第k*2+1个元素。

要找到某个节点时,需要用到二进制表示。比如要找到表示原数组上第6个元素的节点,6的二进制表示是110,去掉开头的1不看,那么表示从根节点先向右走(根据第二位的1),再向左走(根据第三位的0),就到了该节点。

这样子能降低常数,打起来也很方便(不过感觉有点不自然?)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define LX (pos<<1)
 4 #define RX (pos<<1|1)
 5 using namespace std;
 6 int n,m,a[1000100],root[1000100],mem,ch[20000000][2],dat[20000000];
 7 bool g[30];
 8 int glen;
 9 void build(int pos,int& num)
10 {
11     num=++mem;
12     dat[num]=a[pos];
13     if(LX<=n)    build(LX,ch[num][0]);
14     if(RX<=n)    build(RX,ch[num][1]);
15 }
16 int query(int posx,int num)
17 {
18     for(glen=0;posx!=1;posx>>=1)    g[++glen]=(posx&1);
19     for(int i=glen;i>=1;--i)    num=ch[num][g[i]];
20     return dat[num];
21 }
22 int x;
23 void upd_x(int dep,int& num)
24 {
25     int t=num;num=++mem;ch[num][0]=ch[t][0];ch[num][1]=ch[t][1];dat[num]=dat[t];
26     if(!dep)    {dat[num]=x;return;}
27     upd_x(dep-1,ch[num][g[dep]]);
28 }
29 void upd(int posx,int& num)
30 {
31     for(glen=0;posx!=1;posx>>=1)    g[++glen]=(posx&1);
32     upd_x(glen,num);
33 }
34 int main()
35 {
36     int i,ver,idx,pos;
37     scanf("%d%d",&n,&m);
38     for(i=1;i<=n;i++)    scanf("%d",&a[i]);
39     build(1,root[0]);
40     //for(i=1;i<=n;i++)    printf("a%d\n",query(i,root[0]));
41     for(i=1;i<=m;i++)
42     {
43         scanf("%d%d%d",&ver,&idx,&pos);
44         if(idx==1)
45         {
46             scanf("%d",&x);
47             root[i]=root[ver];upd(pos,root[i]);
48         }
49         else
50         {
51             root[i]=root[ver];printf("%d\n",query(pos,root[i]));
52         }
53     }
54     return 0;
55 }

可以把更新也写成非递归。。。

void upd(int posx,int& num)
{
    int t,*t2=&num;for(glen=0;posx!=1;posx>>=1)    g[++glen]=(posx&1);
    for(int dep=glen;dep;--dep)
    {
        t=*t2;*t2=mem++;ch[*t2][0]=ch[t][0];ch[*t2][1]=ch[t][1];dat[*t2]=dat[t];
        t2=&ch[*t2][g[dep]];
    }
    t=*t2;*t2=mem++;ch[*t2][0]=ch[t][0];ch[*t2][1]=ch[t][1];dat[*t2]=dat[t];
    dat[*t2]=x;
}
posted @ 2018-03-08 13:12  hehe_54321  阅读(192)  评论(0编辑  收藏  举报
AmazingCounters.com