热门标签 | 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


推荐阅读
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 本文探讨了随着并发需求的增长,MySQL数据库架构如何从简单的单一实例发展到复杂的分布式系统,以及每一步演进背后的原理和技术解决方案。 ... [详细]
  • 本文探讨如何使用 PHP 进行字符串处理,特别是如何检测一个字符串是否存在于另一个字符串中,并确定其具体位置。通过实例代码展示,帮助读者掌握这一常用功能。 ... [详细]
  • 本文详细介绍了JSP的三大指令:page、include和taglib,重点探讨了静态包含与动态包含的区别及其应用场景,并解释了如何使用taglib指令引入第三方标签库。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • CSS高级技巧:动态高亮当前页面导航
    本文介绍了如何使用CSS实现网站导航栏中当前页面的高亮显示,提升用户体验。通过为每个页面的body元素添加特定ID,并结合导航项的类名,可以轻松实现这一功能。 ... [详细]
  • 在尝试使用C# Windows Forms客户端通过SignalR连接到ASP.NET服务器时,遇到了内部服务器错误(500)。本文将详细探讨问题的原因及解决方案。 ... [详细]
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • 二叉树的链表实现
    本文介绍了一种使用链表结构表示二叉树的方法。通过定义节点结构和相关操作函数,可以方便地创建、插入和遍历二叉树。 ... [详细]
  • 在编译BSP包过程中,遇到了一个与 'gets' 函数相关的编译错误。该问题通常发生在较新的编译环境中,由于 'gets' 函数已被弃用并视为安全漏洞。本文将详细介绍如何通过修改源代码和配置文件来解决这一问题。 ... [详细]
  • 主调|大侠_重温C++ ... [详细]
  • Canvas漫游:碰撞检测与动画模拟
    探索Canvas在Web开发中的应用,通过碰撞检测与动画模拟提升交互体验。 ... [详细]
  • MainActivityimportandroid.app.Activity;importandroid.os.Bundle;importandroid.os.Handler;im ... [详细]
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社区 版权所有