关于离散化权值线段树和动态开点的记录

ps:以下说的"区间"除非强调是权值区间,否则都是下标区间的意思

本文主要记录下,主xi树中一些曾让我困惑的地方

一个疑惑是插入的写法,额还有关于是否要copy旧结点的问题

关于插入数据
1,插入时候,两种更新,一种是pushup形式(就是普通线段树形式),一种是从上而下直接更新(lazy标记永久化写法里好像有这样写过)

//插入写法一,递归到叶子,然后pushup更新sum
void update(int pre,int &now,int l,int r ,int val)
{
    now = ++tot;//每个点必定是新开的
    lch[now] = lch[pre];
    rch[now] = rch[pre];
    // cout<<" now lch rch "<<now<<" "<<l<<" "<<r<<endl;
    if(l==r ) 
    {
        sum[now] = sum[pre] + 1;
        return;
    }
    int mid = (l+r)>>1;
    if( val <= mid ) update(lch[pre],lch[now],l,mid,val);
    else update(rch[pre],rch[now],mid+1,r,val);
    sum[now] = sum[lch[now]] + sum[rch[now]];//pushup
}
//插入的写法二,自上而下地更新sum
void update(int pre,int &now,int l,int r ,int val)
{
    now = ++tot;//每个点必定是新开的
    lch[now] = lch[pre];
    rch[now] = rch[pre];
    sum[now] = sum[pre] + 1;
    if(l==r ) 
    {
        // sum[now] = sum[pre] + 1;
        return;
    }
    int mid = (l+r)>>1;
    if( val <= mid ) update(lch[pre],lch[now],l,mid,val);
    else update(rch[pre],rch[now],mid+1,r,val);
    // sum[now] = sum[lch[now]] + sum[rch[now]];//pushup
}


2,在学树套树的时候,发现树状数组维护的线段树,无需copy。

我的理解是,两个原因,对于一次查询,一个是因为树状数组维护的是log个区间不再是[1,i]而是lowbit~i,还有一个是修改是在线的。
对于区间lowbit~i维护的[1,1e9],我们可以直接修改权值区间,无需copy上一个版本
而求区间第k大那题,为什么需要copy旧版本呢,因为维护的是一个前缀线段树——为了保证[1,i]的信息完整,我们需要将现在改好的一个log长的链,拼到上一个树(即[1,i-1])上以知道[1,i]的信息。
那为什么树套树可以不用呢,因为我们的在线修改就是改的树状数组维护的整个区间lowbit~i,相当于区间第k大那题,我们每次只问1~n区间里第k大的树,那么我们只要维护[1,n]的信息,无需知道任意[1,i]的信息了,两者是等价的。如果要copy的话,也就是我们有知道lowbit~i-1,lowbit~i-2等区间的需求,显然没有...

还有一个疑惑是关于动态开点的定义

问了下庄哥,好像上面所提及的不离散,直接维护[0,1e9]的信息,不算动态开点?就相当于把内存都先开满了N*32,离散化就是可以卡卡常吧
庄哥说他理解的是,用的时候再去申请,一般是带修的问题?更透彻的理解等我再多做点,再补充吧,太菜了现在。
不过不离散的话内存消耗真的很大,带修主席树那题卡空间卡掉了我的define int long long 

n,q=1e5,[0,1e9]离散化后[1,2e5]空间常数从N*30*5到N*18*5还是有点大的

写到这里,临时想起一个疑问就是关于root所维护的区间

主席树模板题,root[i]维护的是[1,i]的根节点,可持久化数组模板题,root[i]维护的是每次修改时的根节点,对于原始数组形成的整棵线段树是存在root[0]里的。。。似乎是看有需求查询的历史版本的时间戳??

有大佬知道话,麻烦解答一下qaq

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值