热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【数据结构】线段数/segmenttree/intervaltree

【线段树】本质是二叉树,每个节点表示一个区间[L,R],设m(R-L+1)2(该处结果向下取整)左孩子区间为[L,m],右孩子区间为[m

【线段树】

  本质是二叉树,每个节点表示一个区间 [ L, R ],设 m = (R - L + 1) / 2  (该处结果向下取整)  左孩子区间为  [ L, m ] , 右孩子区间为 [ m+1 ,  R ]

  同时每个节点(即每个区间)维护一个信息 (该信息能通过子节点区间结果合并得到父区间结果)

  图解:

  例如对于数组[2, 5, 1, 4, 9, 3]可以构造如下的二叉树(背景为白色表示叶子节点,非叶子节点的值是其对应数组区间内的最小值,例如根节点表示数组区间arr[0...5]内的最小值是1):

  区间信息:该区间上的最小值 

  

【应用】

  动态RMQ

    

【模板】

  点修改模板参见例题hdu1754

  区间修改模板(此处有个优化:延迟标记)

  

【例题】

  hdu1754

/*
hdu1754 
找区间最大值 
*/

#include
#include 
#include
using namespace std;

const int INF = -100;
const int maxn = 2000100;
int segtree[maxn];

inline void pushup(int root){
    segtree[root] = max( segtree[root*2], segtree[root*2+1] );
}
void built(int root, int L, int R){
    if(L==R){
        scanf("%d", &segtree[root]);
        return;
    }
    int m = (R+L)/2;
    built(root*2, L, m);
    built(root*2+1, m+1, R);
    pushup(root);
}

//cL current L   cR current right  
int query(int root, int cL, int cR, int qL, int qR){
    if(qL<=cL && cR<=qR) return segtree[root];    //查询区间完全包含当前区间 
    int ans = INF;
    int m = (cR+cL)/2;
    if(qL<=m) ans = max( ans, query(root*2, cL, m, qL, qR) );    //如果查询的区间有部分在当前节点的左子树 
    if(m2+1, m+1, cR, qL, qR) );//如果查询的区间有部分在当前节点的右子树
    return ans; 
}

//修改第p个元素为v 
void update(int root, int cL, int cR, int p, int v){
    if(cL == cR){
        segtree[root] = v;    
        return;
    }
    int m = (cR+cL)/2;
    if(p<=m) update(root*2, cL, m, p, v);
    else update(root*2+1, m+1, cR, p, v);
    pushup(root);
}

int main(){
    int n, m;
    char oder;
    int qL, qR;
    int p, v;
    while(scanf("%d%d", &n, &m)==2){
        built(1, 1, n);
        
        //////    
//            for(int i=1;i<=9;++i) cout <//            cout <
        //////
        
        while(m--){
            getchar(); 
            scanf("%c", &oder);
            if(oder=='Q'){
                scanf("%d%d", &qL, &qR);
                
                //////    
//                    cout <<"qL=" <%d\n", query(1, 1, n, qL, qR));
            }     
            else{
                scanf("%d%d", &p, &v);
                update(1, 1, n, p, v);    
            }
        }
    }
    return 0;
} 
AC

  hdu 1166 求区间和
  hdu 1698 成段更新

//hdu 1698 成段更新
//基础的线段树模板题
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=100005;
int t,n,q;
ll sum[maxn*4],add[maxn*4];
void pushup(int rt){
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,int len){
    if(add[rt]){
        add[rt<<1]=add[rt];
        add[rt<<1|1]=add[rt];
        sum[rt<<1]=add[rt]*(len-(len>>1));
        sum[rt<<1|1]=add[rt]*(len>>1);
        add[rt]=0;
    }
}
void build(int l,int r,int rt){
    add[rt]=0;
    if(l==r){
        //scanf("%I64d",&sum[rt]);
        sum[rt]=1;
        return;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}
void update(int L,int R,int c,int l,int r,int rt){
    if(L<=l&&R>=r){
        add[rt]=c;
        sum[rt]=(ll)c*(r-l+1);
        return;
    }
    pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    if(L<=m) update(L,R,c,l,m,rt<<1);
    if(R>m) update(L,R,c,m+1,r,rt<<1|1);
    pushup(rt);
}
ll querry(int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r) return sum[rt];
    pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    ll ans=0;
    if(L<=m) ans+=querry(L,R,l,m,rt<<1);
    if(R>m) ans+=querry(L,R,m+1,r,rt<<1|1);
    return ans;
}
int main()
{
    int x,y,z;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++){
        scanf("%d%d",&n,&q);
        build(1,n,1);
        while(q--){
            scanf("%d%d%d",&x,&y,&z);
            update(x,y,z,1,n,1);
        }
        printf("Case %d: The total value of the hook is %I64d.\n",cas,querry(1,n,1,n,1));
    }
}
hdu 1698

 

  更多:http://blog.csdn.net/zxy_snow/article/details/6952046

【参考】

  白书P199  

  http://www.cnblogs.com/TenosDoIt/p/3453089.html

  http://blog.csdn.net/zip_fan/article/details/46775633


推荐阅读
  • 本题涉及一个长度为n的序列{ai},代表一系列树木的美学价值。任务是处理m个查询,每个查询提供三个参数l、r和P,目标是在所有满足l < l' ... [详细]
  • 字符串中特定模式出现次数的计算方法
    本文详细探讨了如何高效地计算字符串中特定模式(如'pat')的出现次数,通过实例分析与算法解析,帮助读者掌握解决此类问题的方法。 ... [详细]
  • 本文介绍如何手动实现一个字符串连接函数,该函数不依赖于C语言的标准字符串处理函数,如strcpy或strcat。函数原型为void concatenate(char *dest, char *src),其主要作用是将源字符串src追加到目标字符串dest的末尾。 ... [详细]
  • HTML:  将文件拖拽到此区域 ... [详细]
  • c语言二元插值,二维线性插值c语言
    c语言二元插值,二维线性插值c语言 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 实现系统调用
    实现系统调用一、实验环境​本次操作还是基于上次编译Linux0.11内核的实验环境进行操作。环境如下:二、实验目标​通过对上述实验原理的认识,相信 ... [详细]
  • 编译原理中的语法分析方法探讨
    本文探讨了在编译原理课程中遇到的复杂文法问题,特别是当使用SLR(1)文法时遇到的多重规约与移进冲突。文章讨论了可能的解决策略,包括递归下降解析、运算符优先级解析等,并提供了相关示例。 ... [详细]
  • 题目编号:2049 [SDOI2008]Cave Exploration。题目描述了一种动态图操作场景,涉及三种基本操作:断开两个节点间的连接(destroy(a,b))、建立两个节点间的连接(connect(a,b))以及查询两节点是否连通(query(a,b))。所有操作均确保图中无环存在。 ... [详细]
  • RTThread线程间通信
    线程中通信在裸机编程中,经常会使用全局变量进行功能间的通信,如某些功能可能由于一些操作而改变全局变量的值,另一个功能对此全局变量进行读取& ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • Irish budget airline Ryanair announced plans to significantly increase its route network from Frankfurt Airport, marking a direct challenge to Lufthansa, Germany's leading carrier. ... [详细]
  • 本文介绍了如何通过C#语言调用动态链接库(DLL)中的函数来实现IC卡的基本操作,包括初始化设备、设置密码模式、获取设备状态等,并详细展示了将TextBox中的数据写入IC卡的具体实现方法。 ... [详细]
  • linux网络子系统分析(二)—— 协议栈分层框架的建立
    目录一、综述二、INET的初始化2.1INET接口注册2.2抽象实体的建立2.3代码细节分析2.3.1socket参数三、其他协议3.1PF_PACKET3.2P ... [详细]
  • 前言:由于Android系统本身决定了其自身的单线程模型结构。在日常的开发过程中,我们又不能把所有的工作都交给主线程去处理(会造成UI卡顿现象)。因此,适当的创建子线程去处理一些耗 ... [详细]
author-avatar
Vin-莹持_366
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有