`
128kj
  • 浏览: 614256 次
  • 来自: ...
社区版块
存档分类
最新评论

线段树入门学习(二)(兼解POJ3468) JAVA

阅读更多
继续上文http://128kj.iteye.com/blog/1738772
   在那里用链状结构实现了二叉线段树,下面程序使用一维数组以完全二叉树的方式来存储。

先看一维数组存储线段树到底需要开多大的数组,网上有一个计算程序:
import java.util.Scanner;
/*线段树空间计算程序 Power By:Comzyh*/

 class  segment {//线段树节点
       int b,e;
 }

  public class SegmentTree{//线段树,用数组实现
   static int M=5000000;
   segment seg[];
  
   int Nnode;//节点数
   int LastNode;//最后一个节点
    
    public SegmentTree(){
      seg=new segment[M];
      for(int i=0;i<M;i++)
          seg[i]=new segment();
    }

    
   void build(int b, int e, int root){//构造线段树
     Nnode++;
     if (root>LastNode)
        LastNode=root;
     seg[root].b=b;
     seg[root].e=e;
     if (b==e)
         return;
     int mid =(b+e)>>1;
     build(b,mid,root<<1);
     build(mid+1,e,(root<<1)+1);
   }

   public int getNnode(){
      return Nnode;
   }

   public int getLastNode(){
     return LastNode;
   }

   public static void main(String args[]){
    Scanner in=new Scanner(System.in);
    int N;
    while (true){
          System.out.printf("请输入区间长度:\n");
          N=in.nextInt();
          if (N==0) break;
          SegmentTree st=new SegmentTree();
          st.build(1,N,1);
          System.out.printf("线段树构造完成, 共有%d 节点,最后一个节点是: %d\n",st.getNnode(),st.getLastNode());
          //注意:节点个数总是2N-1
           }
    }
}


运行:
C:\ex>java  SegmentTree
请输入区间长度:
5
线段树构造完成, 共有9 节点,最后一个节点是: 9
请输入区间长度:
10
线段树构造完成, 共有19 节点,最后一个节点是: 25
请输入区间长度:
100000
线段树构造完成, 共有199999 节点,最后一个节点是: 262141

对下面的程序,数组开到300000就可以了。

例:POJ3468

大致题意:给出一个长度为n的整数序列。在这个序列上有两个操作。
其中:
“C a b c”表示区间[a,b]里的所有数都增加c。

“Q a b”表示求出区间[a,b]里的所有数的和。

思路: 线段树+lazy思想:
样例:
Sample Input

10 5  
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15

下面是AC过的代码:
import java.util.Scanner;
import java.io.BufferedInputStream; 
   class Tree{  //线段树节点
        int l, r;  
        long v, add;  
    } 
 public class Main{//数组实现的二叉线段树

    static int N= 100005;  
    Tree node[]=new Tree[N*3];   
    long sum[];
   

     public Main(long[] sum){
       this.sum=sum;
       for(int i=0;i<3*N;i++)
           node[i]=new Tree();
     }

  

    public int L(int u){
        return u << 1;
    }

     public int R(int u) {
      return  u << 1 | 1 ;
    }
      
   public void build ( int u, int l, int r )  //建以r为根的线段树[l,r]
    {  
        node[u].l = l;  
        node[u].r = r;  
        node[u].add = 0;  
        node[u].v = sum[r] - sum[l-1];  
        if ( l == r ) return;  
        int mid = ( l + r ) >> 1;  
        build ( L(u), l, mid );  
        build ( R(u), mid+1, r );  
    }  
      
    public void update ( int u, int l, int r, int val )  //更新
    {  
        if ( l == node[u].l && node[u].r == r )  
        {  
            node[u].add += val;  
            node[u].v += val * ( r - l + 1 );  
            return;  
        }  
      
        if ( node[u].add != 0 )  
        {  
            node[L(u)].add += node[u].add;  
            node[L(u)].v += node[u].add * ( node[L(u)].r - node[L(u)].l + 1 );  
            node[R(u)].add += node[u].add;  
            node[R(u)].v += node[u].add * ( node[R(u)].r - node[R(u)].l + 1 );  
            node[u].add = 0;  
        }  
      
        int mid = ( node[u].l + node[u].r ) >> 1;  
        if ( r <= mid )  
            update ( L(u), l, r, val );  
        else if ( l > mid )  
            update ( R(u), l, r, val );  
        else  
        {  
            update ( L(u), l, mid, val );  
            update ( R(u), mid+1, r, val );  
        }  
        node[u].v = node[L(u)].v + node[R(u)].v;  
    }  
      
    public long query ( int u, int l, int r )  //查询
    {  
        if ( l == node[u].l && node[u].r == r )  
            return node[u].v;  
      
        if ( node[u].add != 0 )  
        {  
            node[L(u)].add += node[u].add;  
            node[L(u)].v += node[u].add * ( node[L(u)].r - node[L(u)].l + 1 );  
            node[R(u)].add += node[u].add;  
            node[R(u)].v += node[u].add * ( node[R(u)].r - node[R(u)].l + 1 );  
            node[u].add = 0;  
        }  
      
        int mid = ( node[u].l + node[u].r ) >> 1;  // 计算左右子结点的分隔点
        if ( r <= mid)  
            return query ( L(u), l, r );  // 和左孩子有交集,考察左子结点
        else if ( l > mid )  
            return query ( R(u), l, r );  // 和右孩子有交集,考察右子结点
        else  
            return query ( L(u), l, mid ) + query ( R(u), mid+1, r );  
    }  
     public static void main(String args[]){

        Scanner in = new Scanner(new BufferedInputStream(System.in));  

          
            int n = in.nextInt();  
            int m = in.nextInt();  
            
            long[] sum=new long[n+1];
            for(int i = 1; i<=n; i++){
              sum[i] = sum[i-1] + in.nextInt();
            }
                 
            Main st=new Main(sum);
            st.build(1,1,n);
            //st.printTree(1);
            String cmd;
            int x;
            int y;
            int c;
            for(int i = 0; i<m; i++)  
            {  
                cmd = in.next();  
                if (cmd.equals("Q")) {  
                 x = in.nextInt();  
                 y = in.nextInt();     
                 System.out.println(st.query(1,x, y));  
                } else {  
                    x = in.nextInt();  
                    y = in.nextInt();     
                    c=in.nextInt();  
                   // System.out.println("c="+c);
                    st.update(1,x,y,c);  
                }  
            }  

      }    
         
    }  
   


样例2:

10 22
1 2 3 4 5 6 7 8 9 10
Q 4 4
C 1 10 3
C 6 10 3
C 6 9 3
C 8 9 -100
C 7 9 3
C 7 10 3
C 1 10 3
Q 6 10
Q 6 9
Q 8 9
Q 7 9
Q 7 10
Q 1 10
Q 2 4
C 3 6 3
Q 9 9
Q 1 1
Q 5 5
Q 6 6
Q 7 7
Q 6 8

ans

4
-82
-104
-147
-122
-100
-37
27
-73
7
14
21
25
-28

源码下载:
  • 大小: 5.4 KB
0
0
分享到:
评论

相关推荐

    线段树入门学习(三)懒操作(兼解POJ1823) JAVA

    在本篇博文中,我们将深入探讨线段树的概念,以及如何实现懒惰更新(Lazy Propagation)策略,同时结合POJ1823问题进行实战应用。懒惰更新是优化线段树性能的关键技巧,它避免了频繁地对每个节点进行更新,从而减少...

    如何学习ACM,看后受益匪浅

    ### 如何学习ACM,看后受益匪浅 #### 一、语言是最重要的基本功 在ACM(Algorithmic Contest and Measurement,算法竞赛)中,编程语言是参赛者必须掌握的第一项技能。根据亚洲赛区的规定,支持的语言主要包括C/...

    医药洁净室空调箱多模式控制程序解析——基于西门子1500 PLC与昆仑通泰触摸屏的应用

    内容概要:本文详细介绍了医药洁净室空调箱的多模式控制程序,涵盖停止模式、生产模式、值班模式、消毒循环模式和消毒排风模式。文中强调了不同模式下的具体控制逻辑及其重要性,并深入探讨了西门子1500 PLC与昆仑通泰触摸屏在博途15编程环境中如何协同工作,实现精准控制。此外,还展示了部分PLC程序代码片段,帮助读者更好地理解和实施这些控制逻辑。 适用人群:从事医药洁净室设计、安装、维护的技术人员,以及对工业自动化控制系统感兴趣的工程师。 使用场景及目标:适用于医药洁净室项目的规划与实施阶段,旨在帮助技术人员掌握空调箱多模式控制的设计思路和技术细节,从而提升系统的可靠性和稳定性。 其他说明:文中提供的示例代码和控制逻辑对于实际工程项目具有较高的参考价值,有助于缩短开发周期,降低调试难度。同时,结合博途15和昆仑通泰触摸屏的实际应用案例,使理论与实践相结合,便于理解和操作。

    【嵌入式系统】STM32F407ZET6驱动HC-SR04超声波模块实现精准测距功能的设计与代码实现文档所属领域(

    内容概要:本文档主要介绍了HC-SR04超声波测距模块的工作原理及其在STM32F407ZET6平台上的应用。HC-SR04超声波测距模块能提供2cm-400cm范围内的非接触式距离感测,精度达3mm。其工作原理是通过TRIG引脚接收触发信号后,自动发送8个40kHz的方波并检测返回信号。若有返回信号,ECHO引脚将输出一个高电平,高电平持续的时间即为超声波往返的时间。根据这个时间可以计算出测试距离。文中还提供了基于STM32F407ZET6平台的C语言代码示例,详细说明了如何配置TRIG和ECHO引脚,以及如何通过测量ECHO引脚高电平持续时间来获取距离值。; 适合人群:对超声波测距模块有一定兴趣,具有嵌入式系统基础知识的研发人员或学生。; 使用场景及目标:①了解HC-SR04超声波测距模块的基本工作原理;②掌握如何在STM32平台上配置和使用HC-SR04模块进行测距。; 其他说明:此文档提供的代码和原理有助于开发者快速上手HC-SR04超声波测距模块的应用开发,建议读者结合实际硬件进行实验以加深理解。

    基于滚动优化的大规模电动汽车充放电策略优化MATLAB代码实现

    内容概要:本文介绍了基于滚动优化的大规模电动汽车充放电策略优化的MATLAB代码实现。文中提出了针对大规模电动汽车调度问题的一种快速优化方法——滚动优化法,并将其与均衡负载法和全局优化法进行了对比。该方法通过将全局问题分解为多个局部子问题,降低了求解复杂度,提高了计算效率。模型考虑了电动汽车的随机到达分布及其充放电策略,目标是最小化电力系统的负荷波动并最大化电动汽车的充放电效益。实验结果显示,滚动优化法在保持电力系统稳定性的前提下显著提升了电动汽车的充放电效益。 适合人群:从事智能交通系统研究、电力系统优化、电动汽车调度等相关领域的研究人员和技术人员。 使用场景及目标:适用于需要优化大规模电动汽车充放电策略的研究项目或实际应用,旨在提升电力系统的稳定性和电动汽车的经济效益。 其他说明:代码基于MATLAB+CVX平台实现,附带详细注释,便于学习和复现。

    基于博途软件的PLC自助洗车机控制系统:全仿真程序、画面、接线图及IO分配表

    内容概要:本文介绍了基于PLC(可编程逻辑控制器)的自助洗车机控制系统的设计与实现。系统采用博途软件编写,实现了从启动到结束的完整洗车流程,包括喷水、刷洗、喷洒清洁剂、吹干等步骤。文中详细描述了洗车机的动作流程、原点复位设计、系统架构、代码与控制逻辑分析,并提供了人机界面、接线图和IO分配表等辅助资料。此外,还强调了系统的稳定性和优质售后服务。 适合人群:从事自动化控制领域的工程师和技术人员,特别是对PLC编程和洗车机控制系统感兴趣的读者。 使用场景及目标:适用于需要了解或开发自助洗车机控制系统的场合,旨在帮助读者掌握PLC编程技巧和洗车机的工作原理,提高系统的稳定性和可靠性。 其他说明:本文不仅提供了详细的硬件和软件设计方案,还涵盖了故障处理和售后服务的内容,确保系统的长期稳定运行。

    【嵌入式系统】STM32F407ZET6 GPIO接口详解:输入输出模式与应用实例介绍文档的主要内容

    内容概要:本文档详细介绍了STM32F407ZET6的GPIO(通用输入输出接口)。GPIO在输出模式下能控制端口输出高低电平,适用于驱动LED、控制蜂鸣器等;在输入模式下可读取端口的高低电平或电压,如读取按键输入、ADC电压采集等。每个通用I/O端口包含多个32位配置寄存器、数据寄存器等。文档列举了GPIO的八个功能模式,重点解析了输出状态中的推挽输出和开漏输出,以及输入状态中的下拉电阻和上拉电阻的概念与工作原理。推挽输出可输出高低电平,由两个互补的晶体管提供较大电流驱动;开漏输出通常只能输出低电平,适合电平转换。输入状态方面,下拉电阻将信号初始化为低电平,上拉电阻则初始化为高电平,其本质分别是输出和注入电流。; 适合人群:嵌入式系统开发人员、电子工程师、对STM32微控制器有兴趣的学习者。; 使用场景及目标:①帮助开发者理解STM32F407ZET6的GPIO工作机制;②为实际项目中GPIO的应用提供理论指导,如控制外部设备、读取传感器数据等。; 其他说明:文档提供了详尽的寄存器配置信息和功能模式介绍,有助于深入理解和灵活运用GPIO接口。建议读者结合实际硬件操作进行学习,以加深理解。

    两电平三相并网逆变器的有限控制集模型预测控制(FCS-MPC)代码实现与波形分析

    内容概要:本文详细介绍了两电平三相并网逆变器的有限控制集模型预测控制(FCS-MPC)的代码实现方法。首先设置了系统的参数,如滤波电感、等效电阻、控制周期等。接着阐述了离散化状态方程和代价函数的设计,其中代价函数考虑了电流跟踪误差和开关损耗。然后展示了主控制循环的具体实现,通过遍历所有可能的开关状态选择最优的动作。最后对仿真效果进行了分析,指出了常见的问题及解决方案,如采样同步、权重系数调整和离散化精度等问题。 适合人群:电力电子领域的初学者和技术爱好者,尤其是对逆变器控制策略感兴趣的读者。 使用场景及目标:适用于需要理解和实现两电平三相并网逆变器FCS-MPC控制的人群。目标是掌握FCS-MPC的工作原理,能够独立完成相关代码编写,并能进行基本的参数调整和优化。 其他说明:文中提供了详细的代码片段和仿真波形图,帮助读者更好地理解理论与实践的结合。同时附有参考文献,方便进一步深入学习。

    CST仿真超表面技术实现线极化转圆极化极化转换器的研究与文献复现

    内容概要:本文详细介绍了利用CST微波工作室进行超表面仿真,将线极化波转化为圆极化波的技术实现过程。首先,构建了一个简单的十字形金属贴片作为超表面单元模型,设置了金属层和基板的具体参数。接着,通过调整X和Y方向的相位差达到90度来实现极化转换,并使用VBA脚本进行参数优化。最终,在12.5GHz频率处实现了低于3dB的轴比,验证了圆极化的成功转换。此外,还讨论了网格划分对仿真的影响,指出六边形网格相比矩形网格能更快收敛。 适合人群:从事电磁仿真、天线设计以及超表面研究的专业技术人员。 使用场景及目标:适用于需要深入了解线极化转圆极化技术原理及其实际应用的研究人员和技术开发者。目标是掌握CST仿真工具的操作技巧,理解极化转换的关键技术和优化方法。 其他说明:文中提供了详细的建模步骤、参数设置和代码片段,有助于读者快速上手并复现实验结果。同时提醒注意网格划分的选择,以提高仿真效率。

    全国大学生电子设计竞赛论文模板(20190717084742).pdf

    电子设计竞赛相关资源

    Modbus RTU协议在STC32G与STC8系列单片机上的优化实现及应用

    内容概要:本文详细介绍了新版Modbus RTU从机源码针对STC32G和STC8系列单片机的优化改进。主要改进包括硬件CRC加速、动态内存分配机制、自动波特率检测等功能特性。文中对比了新旧版本的性能差异,特别是在CRC校验效率提升、内存管理和通信稳定性方面的显著进步。此外,还提供了与多种组态软件的适配方法,如威纶通触摸屏的地址映射技巧,以及ModbusPoll工具的预配置模板,帮助开发者快速搭建和调试系统。 适合人群:嵌入式系统开发工程师,尤其是熟悉STC系列单片机和Modbus协议的开发者。 使用场景及目标:适用于工业自动化控制系统中需要高效稳定通信的应用场景,旨在提高系统的实时性和可靠性,降低开发难度并缩短产品上市周期。 其他说明:文中提到的部分技术细节(如硬件CRC、动态内存分配)可能不适合所有应用场景,在具体项目中可根据实际情况选择是否采用。对于初次接触Modbus协议的新手来说,建议先掌握基础知识再深入研究本文提供的高级特性。

    实训商业源码-工作场所技能必不可少的应用程序主页模板-毕业设计.zip

    实训商业源码-工作场所技能必不可少的应用程序主页模板-毕业设计.zip

    110kV变电站电气一次设计:主接线方案、短路电流计算及设备选型详解

    内容概要:本文详细介绍了110kV变电站电气一次设计的关键步骤和技术要点。首先,通过对原始参数的解读,明确了变电站的基本要求。接着,重点讨论了主接线方案的选择,通过案例分析展示了双母线接线方式的优势。随后,深入探讨了短路电流计算的重要性及其对电网安全的影响。最后,针对电气一次设备的选型进行了全面分析,强调了质量和效率的平衡。整个设计过程最终通过AutoCAD2014绘制出了详细的主接线A0大图。 适合人群:从事电力系统设计、运行和维护的专业技术人员,尤其是对110kV变电站电气一次设计感兴趣的工程师。 使用场景及目标:适用于新建设或改造110kV变电站项目,帮助设计师优化主接线方案,提高电网的安全性和可靠性,同时降低运营成本。 其他说明:文中提供了具体的CAD绘图命令片段作为参考,有助于读者更好地理解和应用相关设计方法。

    实训商业源码-抽奖页面小程序模板-毕业设计.zip

    实训商业源码-抽奖页面小程序模板-毕业设计.zip

    电力系统中基于39节点故障数据的短路分析与负荷仿真实验

    内容概要:本文详细介绍了基于39节点故障数据的短路分析与负荷仿真实验。文中首先概述了故障数据的特点,指出故障主要集中在特定区域的多个节点上,短路持续时间和负荷水平存在显著差异。接着,文章描述了仿真的具体过程和方法,强调了采用先进技术进行多场景下电网运行的模拟。仿真结果显示,短路点分布广泛,短路持续时间从数小时到数天不等,负荷水平变化范围大。此外,还讨论了数据处理技术和仿真模型构建的关键步骤,提出了故障应对中的安全保障措施。最后,作者总结了研究的重要性和对未来工作的建议,如加强电网监控、提升应急响应能力和推进智能化电网建设。 适合人群:从事电力系统研究、电网管理和维护的技术人员及研究人员。 使用场景及目标:适用于希望深入了解电网故障分析和负荷仿真技术的专业人士,旨在提高电网运行的可靠性和稳定性。 阅读建议:读者可以通过本文了解电网故障的具体表现形式及其对电网运行的影响,掌握先进的仿真技术和数据处理方法,从而为实际工作中遇到的问题提供解决方案。

    (addon.py):Blender MCP插件

    MCP插件(addon.py):Blender插件,在Blender中创建一个套接字服务器来接收和执行命令

    基于Qt框架的最小生成树算法(Prim和Kruskal)动态可视化实现及其应用

    内容概要:本文介绍了利用Qt框架实现Prim和Kruskal两种最小生成树算法的动态可视化项目。该项目不仅展示了这两种算法的具体执行过程,还提供了详细的源代码和技术解析。Prim算法通过维护两个节点集合之间的最短边进行构建,而Kruskal算法则借助并查集防止形成环路。两者均实现了动态展示,使算法执行过程如同观看动画般直观。此外,文中还提到了一些实现细节,如优先队列的特殊使用方法、多线程环境下的数据同步以及图形化界面的设计。 适合人群:计算机科学专业学生、算法爱好者、软件开发者。 使用场景及目标:本项目的应用场景主要是在教学环境中用于讲解最小生成树算法的工作机制,帮助学习者更好地理解和掌握相关概念;同时也适用于希望深入研究这两类算法实现方式的研究人员。 其他说明:附带完整的源代码和一份详尽的技术报告,涵盖从理论分析到实际编码过程中遇到的问题及解决方案。

    电力电子领域中基于滞环电流控制的VIENNA整流器技术研究与优化

    内容概要:本文详细介绍了基于滞环电流控制的VIENNA整流器的技术特点和工作原理。首先概述了VIENNA整流器作为一种高效AC-DC转换器的独特优势,如高功率因数、低谐波失真和高效率。接着阐述了滞环电流控制技术的基本原理,即通过实时检测和比较实际电流与给定电流的偏差,控制开关器件的通断,实现电流的精确控制。然后具体解释了基于滞环电流控制的VIENNA整流器的工作机制,强调其快速响应、高精度和低噪声的特点。最后总结了该整流器的多项优点,包括高效率、快速响应、高功率因数和较低的谐波失真,指出其在未来电力电子系统中的广泛应用前景。 适合人群:从事电力电子技术研究和开发的专业人士,以及对高效AC-DC转换器感兴趣的工程技术人员。 使用场景及目标:适用于需要深入了解VIENNA整流器及其控制技术的研究人员和技术人员,旨在提升对电力转换系统的理解和优化能力。 其他说明:本文不仅提供了理论分析,还讨论了实际应用中的优化策略,有助于推动相关技术的进步和发展。

    实训商业源码-单个商品销售系统源码-毕业设计.zip

    实训商业源码-单个商品销售系统源码-毕业设计.zip

Global site tag (gtag.js) - Google Analytics