线段树操作及其模板

线段树--概念+模板+入门题 引子 子问题–1 给出n个数,m次问询,每次问询给出一个范围l、r,求区间l–r的总和 很容易想到用前缀和可以解决 O(n) 子问题–2 给出n个数,m次修改,每次给出一个范围l、r和一个值k,将区间l—r的数全部+k,m次修改后,再问询1次求区间l–r的总和 也可以想到这用差分就能解决 O(n) 最后将这两个问题结合起来,给出n个数,m次操作,操作有两种一个是将区间l–r的值+k,一个是询问区间l–r的总和。 这个问题与之前不同的地方是,之前想要求一个范围只需处理一次数据算前缀和,然后数据不变,可以一 阅读详情
#include<iostream>
#include<cstdio>
using namespace std;
struct node
{
    long long l,r,v,f;
} tree[400000];
long long ans,x,y,z;
void down(long long i)//懒标记 进行区间更新 并将懒标记下传
{
    tree[i*2].v=(tree[i*2].r-tree[i*2].l+1)*tree[i].f;
    tree[i*2].v=(tree[i*2].r-tree[i*2].l+1)*tree[i].f;
    tree[i*2].f+=tree[i].f;
    tree[i*2+1].f+=tree[i].f;
    tree[i].f=0;
}
void build(long long i,long long l,long long r)
{
    tree[i].l=l;
    tree[i].r=r;
    tree[i].v=0;
    if(l==r)
    {
        scanf("%lld",&tree[i].v);
        return ; //一定要加上return 否则程序会崩溃
    }
    long long mid=(l+r)/2;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
    tree[i].v=tree[i*2].v+tree[i*2+1].v;
}
void add(long long i)
{
    if(tree[i].l==tree[i].r)
    {
        tree[i].v+=y;
        return ;
    }
    if(tree[i].f)
    {
        down(i);
    }
    long long mid=(tree[i].l+tree[i].r)/2;
    if(x<=mid)
    {
        add(2*i);
    }
    else
    {
        add(2*i+1);
    }
    tree[i].v=tree[i*2].v+tree[i*2+1].v;
}
void sum(long long i)
{
    if(tree[i].l>=x&&tree[i].r<=y)
    {
        ans+=tree[i].v;
        return ;
    }
    if(tree[i].f)
    {
        down(i);
    }
    long long mid=(tree[i].l+tree[i].r)/2;
    if(x<=mid)
    {
        sum(2*i);
    }
    if(y>mid)
    {
        sum(2*i+1);
    }
}
void pluss(long long i)
{
    if(tree[i].l>=x&&tree[i].r<=y)
    {
        tree[i].f+=z;
        tree[i].v+=z*(tree[i].r-tree[i].l+1);
        return ;
    }
    if(tree[i].f)
    {
        down(i);
    }
    long long mid=(tree[i].l+tree[i].r)/2;
    if(x<=mid)
        pluss(i*2);
    if(y>mid)
        pluss(i*2+1);
}
int main()
{
    int op,n,m;
    while(cin>>n)
    {
        build(1,1,n);
        cin>>m;
        while(m--)
        {
            cin>>op;
            if(op==1)
            {
                scanf("%lld%lld",&x,&y);
                add(1);
            }
            else if(op==2)
            {
                scanf("%lld%lld",&x,&y);
                ans=0;
                sum(1);
                cout<<ans<<endl;
            }
            else
            {
                scanf("%lld%lld%lld",&x,&y,&z);
                pluss(1);
            }
        }
    }
    return 0;
}

校赛例题
玄黄最近发明了一个神奇的函数:
Xh(x)=3*( ∑(x的每一位) )+1 ,x为自然数。
现在你面前有n个自然数,玄黄现在要求你完成两种操作 。
1、帮玄黄求出这n个数中,区间 [l, r] 的和,并把答案告诉玄黄 。
2、帮玄黄把区间 [l, r] 中的每一个数 x 都变成 Xh(x)
第一行输入一个正整数n(0 第二行输入n个自然数,下标从 1 至 n,每个自然数大小不超过 100000000003。
第三行输入一个正整数m(0 之后有m行,每行输入三个数op, l, r( 0 < op < 3, 1 <= l <=r <=n ),op 代表玄黄要求你的操作编号,op 为 1 时执行第一种操作,op 为 2 时执行第二种操作,l 和 r 代表区间范围 。

分析:一个自然数 经过有限次的xh变换 总会变成13的,对于一些区间和已经变成13的节点我们可以不进行操作,这样就省了大量的时间。

#include<iostream>
#include<string.h>
#include<cstdio>
using namespace std;
long long x,y,ans;
struct node
{
    long long l,r,v,f;//如果该区间的sum为13则f=1,否则为0
}tree[120000];
void build(long long i,long long l,long long r)
{
    tree[i].l=l;
    tree[i].r=r;
    tree[i].f=0;
    if(l==r)
    {
        scanf("%lld",&tree[i].v);
        if(tree[i].v==13)
            tree[i].f=1;
        return ;
    }
    long long mid=(l+r)/2;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    tree[i].v=tree[i<<1].v+tree[i<<1|1].v;
    tree[i].f=min(tree[i<<1].f,tree[i<<1|1].f);
}
void sum(long long i)
{
    if(tree[i].l>=x&&tree[i].r<=y)
    {
        ans+=tree[i].v;
        return ;
    }
    long long mid=(tree[i].l+tree[i].r)/2;
    if(x<=mid)
    {
        sum(i<<1);
    }
    if(y>mid)
    {
        sum(i<<1|1);
    }
}
void xh(long long i)
{
    if(tree[i].f)
    {
        return ;
    }
    long long mid=(tree[i].l+tree[i].r)/2;
    if(tree[i].l==tree[i].r)
    {
        long long sum=0;
        while(tree[i].v)
        {
            sum+=tree[i].v%10;
            tree[i].v/=10;
        }
        tree[i].v=sum*3+1;
        if(tree[i].v==13)
        {
            tree[i].f=1;
        }
        return ;
    }
    if(x<=mid)
    {
        xh(i<<1);
    }
    if(y>mid)
    {
        xh(i<<1|1);
    }
    tree[i].v=tree[i<<1].v+tree[i<<1|1].v;
    tree[i].f=min(tree[i<<1].f,tree[i<<1|1].f);
}
int main ()
{
    int n,m,op;
    cin>>n;
    build(1,1,n);
    cin>>m;
    while(m--)
    {
        scanf("%d",&op);
        scanf("%lld%lld",&x,&y);
        if(op==1)
        {
            ans=0;
            sum(1);
            printf("%lld\n",ans);
        }
        else
        {
            xh(1);
        }
    }
    return 0;
}

权值线段树 详解+操作模板(c++) 权值线段树详解+模板代码+例题 阅读详情

相关推荐

线段树模板

手打了一份线段树代码,用于c++编程, 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。 使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,实际应用时一般还要开4N的数组以免越界,因此有时需要离散化让空间压缩。

线段树的四种模板

第一种模板只适合单点修改的题目,每次修改都传递到树的子节点。对于区间修改则不合适,同时,由于数组大小事先申明好,其点数也有上限。为了解决数据量的问题,这里提供了动态开点,解除了每个树的元素都占一个固定坑位的限制。但是仍然有限制,点数不可以随便加,有上限。和第一套模板相比,增加了区间修改的功能。但是点数仍然有上限,数据量顶多十万,再往上就不能适用了。点数无限制,需要的时候申请,但是效率会很低。...

lhm的博客 4483

OCSP环境搭建--Windows Server 2016

OCSP环境搭建--Windows Server 2016 一. OCSP环境中相关信息 1. 服务器1 操作系统:Win Server 2016 Standard版 IP地址:172.16.0.19/23,网关:172.16.0.1,首选DNS:127.0.0.1 服务器角色:域控制器、证书颁发机构、radius服务器、DNS服务器 ...

CsdnCHong_566的博客 3351

线段树(原理,模板)

算法——数据结构——线段树

CegghnnoR的博客 1394

vue3的面试题

vue3的面试题

jiang7701037的博客 6264

无人驾驶感知融合——横摆角速度的多源估计算法解析

本文深入解析了无人驾驶感知融合中的横摆角速度多源估计算法,详细介绍了轮速差法、侧向加速度法、曲率法和惯性传感器直读法四种计算方法及其优缺点。通过卡尔曼滤波实战案例,展示了多源融合算法在提升精度和稳定性方面的显著优势,并探讨了工程实践中的时间对齐、坐标系统一等关键问题。

weixin_31458015的博客 462

你真的懂线段树的 lazy 操作吗,万字解析带你彻底掌握,从此不再需要模板。

我认为,理解lazylazy操作会遇到的第一个困难是,对lazytaglazytag没有清晰确定的定义。比如当一个结点nodenode的加法标记lazyaddxlazyaddx,这意味着什么?我们的回答可能是:“意味着这个结点所代表的区间都欠着一个常数x\mathrm{x}x需要被累加”。这句话是对的,但不够细致,当我们真正地去实现一棵线段树时,我们就会感觉到这个定义是不够细致的。这个问题具体地说就是,如果一个结点u\mathrm{u}

louisdlee的博客 924

手把手教你用ComfyUI搭建高效AI绘画工作流:从基础到高级技巧

本文详细介绍了如何使用ComfyUI构建高效的AI绘画工作流,从基础配置到高级技巧全面覆盖。通过模块化设计,ComfyUI显著提升显存利用率和创作灵活性,适合从新手到专业用户。文章包含部署指南、工作流搭建、性能优化及行业应用案例,帮助读者快速掌握AI绘画核心技术。

7up55的博客 718

线段树最基本的所有操作模板

给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。 2、“Q l r”,表示询问 数列中第 l~r 个数的和。 对于每个询问,输出一个整数表示答案。 输入格式 第一行两个整数N,M。 第二行N个整数A[i]。 接下来M行表示M条指令,每条指令的格式如题目描述所示。 输出格式 对于每个询问,输出一个...

qq_45772483的博客 192

SAP ABAP 实用小技巧合集 (一)

本合集包含了笔者从事 ABAP 开发 17 年以来积累的小技巧。持续更新。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 3218

YOLOv8【第九章:模型部署篇·第2节】一文搞懂,模型剪枝与压缩技术!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏。该专栏系统复现并梳理全网各类 YOLOv8 改进与实战案例(当前已覆盖分类 / 检测 / 分割 / 追踪 / 关键点 / OBB 检测等方向),坚持持续更新 + 深度解析,质量分长期稳定在 97 分以上,可视为当前市面上 覆盖较全、更新较快、实战导向极强 的 YOLO 改进系列内容之一。

**My Coding Family** 1525

有关线段树的基本操作模板

定义 基本操作 构建线段树 区间查询 更新某个叶子节点的值 定义 只是怕你们忘了 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长

Harrys_Snitch 576

《模型轻量化-剪枝蒸馏量化系列》YOLOv5无损剪枝(附源码)

无损剪枝模型到几百kb~

cv君的博客 3万+

【常用模板】 线段树单点操作

输入 第一行两个整数n,m,第二行n个整数表示初始时的数组A[ ]; 接下来m行,每行3个整数a,b,c,如果a=1,那么输出A[b]~A[c]中最大的数 若a=2,那么将A[b]改为c 输出 每行输出一个整数,对应每一个操作a=1 超级简单的线段树模板题,一遍就过了,子程序太多,变量更多,容易搞混很尴尬,就在几周前的noip中,有一个dalao给我们得瑟说他会线段树,

Mengbier's Home 366

华为FusionCompute之计算虚拟化

华为FusionCompute之虚拟化

jks212454的博客 2452

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

高级数据结构(三)——线段树之基本操作与模板例题

线段树之基本操作与模板例题 一、什么是线段树? 1.1、线段树解决什么样的问题? 线段树是针对区间问题进行操作的高级数据结构,有这么一类RMQ问题(区间最值查询),是线段树的典型代表。如下: 给你一个长度为 n 的数列:{a1, a2, a3, a4, a5, a6, …… , an},需要进行一下操作: ①、区间最值:给定:1 <= i <= j <= n,要 q 次查询区间 :[i, j]的最值 ②、单点修改:给定某单点:k 和 x,要求吧第 k 个元素:ak = x ③、区间求和:给

qq_44274276的博客 368

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【模板】线段树+懒操作

题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[...

weixin_30645617的博客 160

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

HDU1754(线段树模板题)(没有用懒操作)

题目链接/*** * 线段树第二弹 * 模板题 * hdu1754 */#include<iostream> #include<cstdio> #include<algorithm>using namespace std; #define lc (d<<1) #define rc (d<<1|1) #define mid (l+r>>1) const int mmax = 200002;in

youcanyouup 318

P6242 【模板】线段树 3(区间最值操作、区间历史最值)

很显然,第一遍自己打的代码是没有仔细思考pushdown和pushup的。这道题也是一道模板题,需要学一下思路,然后把板子记住。用线段树维护一个区间最大值、区间最小值。那个B数组不纯纯来捣乱的吗。先记住现在过了的模板吧。

weixin_73683197的博客 580

洛谷P6242 【模板】线段树 3(区间最值操作、区间历史最值)

给出一个长度为 n 的数列 A,同时定义一个辅助数组 B,B 开始与 A 完全相同。因为只有在区间只有一种数大于 k 的时候我们才能快速更新,即只能在满足 semax <k< tree2 的节点上更新。对于 op∈{3,4,5} 的操作,输出一行包含一个整数,表示这个询问的答案。在每一次操作后,我们都进行一次更新,让 Bi​←max(Bi​,Ai​)。第二行包含 n 个整数 A1​,A2​,⋯,An​,表示数列 A。semax:该区间的严格次大值,也就是最大的比最大值小的值。这是一道吉司机线段树的模板题。

2301_80812282的博客 433

【洛谷 P3372】【模板】线段树 1 pushdown 操作

题目描述 如题,已知一个数列,你需要进行下面两种操作: 将某区间每一个数加上 kk。 求出某区间每一个数的和。 输入格式 第一行包含两个整数 n, mn,m,分别表示该数列数字的个数和操作的总个数。 第二行包含 nn 个用空格分隔的整数,其中第 ii 个数字表示数列第 ii 项的初始值。 接下来 mm 行每行包含 33 或 44 个整数,表示一个操作,具体如下: 1 x y k:将区间 [x, y...

待到山花烂漫时 309

【常用模板】 线段树区间操作

线段树 非常简单的线段树 区间操作,比单点操作难那么一点点(一点点?)但是……似乎……并没有这么简单,这么多的子程序,检查比写都难,可我一直把想要求的区间左右端点和当前端点混着用,就一直不过,很尴尬 #include #include using namespace std; int a[110000]; struct tree{ long long l,r,sum,addi,len; }

Mengbier's Home 272
上一篇: 快速幂及矩阵快速幂——加快运算
下一篇: 数据结构之线性表及其基本操作
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值