首页 > 其他分享 >动态开点线段树

动态开点线段树

时间:2022-11-22 09:33:53浏览次数:50  
标签:return val int 线段 mid 动态 sum

简单来说就是,你要用到一个点才开那个点,不用的点不开,可以大幅节省空间。
这样空间复杂度可以大致降到O(nlogn)。
是不是很棒。
接下来是实现:
一开始,你只有一个根节点。
通过update函数往树里面插点,开两个数组记录每个节点的左右儿子编号。
递归进入左右儿子,如果要用新点,就开新点。
上代码(以区间和为例):
插入

inline void update(int &o,int l,int r,int x,int val){
    if(!o)o=++ncnt;
    if(l==r){
        sum[o]+=val;return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)update(lc[o],l,mid,x,val);
    else update(rc[o],mid+1,r,x,val);
    pushup(o);
}

查询

int ask(int o,int l,int r,int L,int R){
    if(!o)return 0;
    if(L<=l && R>=r)return sum[o];
    int val=0;
    int mid=(l+r)>>1;
    if(L<=mid)val+=ask(lc[o],l,mid,L,R);
    if(R>mid)val+=ask(rc[o],mid+1,r,L,R);
    return val;
}

其它操作跟线段树是一样的,你只要把普通线段树里的p<<1换成lc[p],p<<1|1换成rc[p]就行了。
我上一篇的线段树也是记录了左右儿子编号的,其实没有必要,只是为了这一篇做个铺垫。
灵活运用动态开点线段树可以节省很多内存,而且能做到普通线段树做不到的事情。
比如题目要求在线操作不能离散化,值域又特别大:inf,并且询问q不大
这时候我们就可以用动态开点线段树开qloginf个点过掉这题。
是不是很美妙。
完整代码

#include<bits/stdc++.h>
#define LOG 20
using namespace std;const int maxn=100010;
int rt,ncnt,lc[maxn*LOG],rc[maxn*LOG],sum[maxn*LOG];
inline void pushup(int o){
    sum[o]=sum[lc[o]]+sum[rc[o]];//更新
}
inline void update(int &o,int l,int r,int x,int val){
    if(!o)o=++ncnt;//开点
    if(l==r){
        sum[o]+=val;return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)update(lc[o],l,mid,x,val);
    else update(rc[o],mid+1,r,x,val);
    pushup(o);
}
int ask(int o,int l,int r,int L,int R){
    if(!o)return 0;//没这个点,直接返回0
    if(L<=l && R>=r)return sum[o];
    int val=0;
    int mid=(l+r)>>1;
    if(L<=mid)val+=ask(lc[o],l,mid,L,R);
    if(R>mid)val+=ask(rc[o],mid+1,r,L,R);//递归计算
    return val;
}
int main(){
    int n;cin>>n;
    for(int i=1;i<=n;i++){
        int num;cin>>num;
        update(rt,1,n,i,num);
    }
    int q;cin>>q;
    while(q--){
        int l,r;cin>>l>>r;
        cout<<ask(rt,1,n,l,r)<<endl;
    }
}

  

标签:return,val,int,线段,mid,动态,sum
From: https://www.cnblogs.com/smghj/p/16914124.html

相关文章

  • 依据前端返回参数,动态构建lambda表达式
    1、构建前端返回类///<summary>///查询明细///</summary>publicclassQueryItem{///<summary>///查询项字段///......
  • 动态规划——数据结构与算法学习
    动态规划动态规划的原理其实也是将大问题划分为小问题,从而一步步获取最优解,但是适用于动态规划求解的问题,子问题往往不是独立的,是具有相互关联性。背包问题有一个背包,容......
  • tomcat_动态java项目的目录结构、与idea集成&创建web项目
    tomcat_动态java项目的目录结构静态项目和动态项目:目录结构:java动态项目的目录结构:项目的根目录WEB-INF目录:......
  • 【算法提高课】动态规划笔记
    单调队列优化DP可以开个结构体存下标和值,不用只存下标,不容易写错;此类问题一般都有烦人的边界问题,需要细心处理;单调队列可以换成优先队列,复杂度会多个\(log\)。推出式......
  • 动态路由name重复的问题
    今天写路由白名单的时候出现了一个vue路由警告:Duplicatenamedroutesdefinition,我不是问题的解决者,我只是解决问题文章的搬运工-3-https://blog.csdn.net/qq_37026254......
  • 唯美动态壁纸
    唯美动态壁纸 动态壁纸让您轻松自己来设计图片(通过选择相册或者拍照来完成),实现:“我的桌面我做主”,本身提供漂亮,性感,可爱的超美女照片,给你视觉的冲击和精神的享受。具体使用......
  • 案例_动态表格_添加和删除
    案例_动态表格_添加和删除分析:1,添加1.给添加按钮绑定事件2.获取文本框内容3.创建td设置td的文本框的内容4.创建tr......
  • python画动态爱心
    importrandomfrommathimportsin,cos,pi,logfromtkinterimport*CANVAS_WIDTH=640#画布的宽CANVAS_HEIGHT=480#画布的高CANVAS_CENTER_X=CANVA......
  • P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
    有一说一,雨天的尾巴我其实骂了很久。主要是题面之前一直没耐心读,然后后面在其他地方看到了形式化题意,就做掉了。其实感觉有很多题都比这玩意适合当板子,所以这个迟到的板子......
  • 代码随想录第四十一天|动态规划
    今天是四十一天,从今天起难度大概就要上来了 343.整数拆分classSolution{publicintintegerBreak(intn){int[]dp=newint[n+1];dp[2]......