线段树——懒标记下放
创始人
2024-06-03 17:26:38
0

【模板】线段树 1

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  1. 将某区间每一个数加上 kkk。
  2. 求出某区间每一个数的和。

输入格式

第一行包含两个整数 n,mn, mn,m,分别表示该数列数字的个数和操作的总个数。

第二行包含 nnn 个用空格分隔的整数,其中第 iii 个数字表示数列第 iii 项的初始值。

接下来 mmm 行每行包含 333 或 444 个整数,表示一个操作,具体如下:

  1. 1 x y k:将区间 [x,y][x, y][x,y] 内每个数加上 kkk。
  2. 2 x y:输出区间 [x,y][x, y][x,y] 内每个数的和。

输出格式

输出包含若干行整数,即为所有操作 2 的结果。

样例 #1

样例输入 #1

5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4

样例输出 #1

11
8
20

提示

对于 30%30\%30% 的数据:n≤8n \le 8n≤8,m≤10m \le 10m≤10。
对于 70%70\%70% 的数据:n≤103n \le {10}^3n≤103,m≤104m \le {10}^4m≤104。
对于 100%100\%100% 的数据:1≤n,m≤1051 \le n, m \le {10}^51≤n,m≤105。

保证任意时刻数列中所有元素的绝对值之和 ≤1018\le {10}^{18}≤1018。

【样例解释】

懒标记用于计算每个线段的变化程度,在这题就是每个线段增加的数之和,当我们的add操作和query操作都没有遍历到所输入的x y的时候,我们就需要不断的把懒标记进行下放,下放完之后我们还得记得维护f的值,使其不失真,具体看代码

#include
#define ll long long
using namespace std;
ll f[400005],v[400005];
int n,m,a[100005];
inline void buildtree(int k,int l,int r){if(l==r){f[k]=a[l];return;}int mid=(l+r)>>1;buildtree(k<<1,l,mid);buildtree(k<<1|1,mid+1,r);f[k]=f[k<<1]+f[k<<1|1];
}
inline void push_down(int k){//将懒标记点下放v[k<<1]+=v[k],v[k<<1|1]+=v[k],v[k]=0;
}
inline void push_up(int k,int l,int r,int m){//维护f[k]的值,使其不失真f[k]=f[k<<1]+v[k<<1]*(m-l+1)+f[k<<1|1]+v[k<<1|1]*(r-m);
}
inline void add(int k,int l,int r,int x,int y,int num){if(l==x&&r==y){v[k]+=num;return;}if(v[k])push_down(k);int mid=(l+r)>>1;if(y<=mid)add(k<<1,l,mid,x,y,num);elseif(x>mid)add(k<<1|1,mid+1,r,x,y,num);else add(k<<1,l,mid,x,mid,num),add(k<<1|1,mid+1,r,mid+1,y,num);push_up(k,l,r,mid);
}
inline ll query(int k,int l,int r,int x,int y){if(l==x&&r==y)return f[k]+v[k]*(r-l+1);if(v[k])push_down(k);int mid=(l+r)>>1;ll res;if(y<=mid)res=query(k<<1,l,mid,x,y);elseif(x>mid)res=query(k<<1|1,mid+1,r,x,y);else res=query(k<<1,l,mid,x,mid)+query(k<<1|1,mid+1,r,mid+1,y);push_up(k,l,r,mid);return res;
}
int main(){cin>>n>>m;for(int i=1;i<=n;++i)scanf("%d",&a[i]);buildtree(1,1,n);while(m--){int t,x,y,num;scanf("%d%d%d",&t,&x,&y);if(t==1){scanf("%d",&num);add(1,1,n,x,y,num);}else cout<

【模板】线段树 2

题目描述

如题,已知一个数列,你需要进行下面三种操作:

  • 将某区间每一个数乘上 xxx

  • 将某区间每一个数加上 xxx

  • 求出某区间每一个数的和

输入格式

第一行包含三个整数 n,m,pn,m,pn,m,p,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含 nnn 个用空格分隔的整数,其中第 iii 个数字表示数列第 iii 项的初始值。

接下来 mmm 行每行包含若干个整数,表示一个操作,具体如下:

操作 111: 格式:1 x y k 含义:将区间 [x,y][x,y][x,y] 内每个数乘上 kkk

操作 222: 格式:2 x y k 含义:将区间 [x,y][x,y][x,y] 内每个数加上 kkk

操作 333: 格式:3 x y 含义:输出区间 [x,y][x,y][x,y] 内每个数的和对 ppp 取模所得的结果

输出格式

输出包含若干行整数,即为所有操作 333 的结果。

样例 #1

样例输入 #1

5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4

样例输出 #1

17
2

提示

【数据范围】

对于 30%30\%30% 的数据:n≤8n \le 8n≤8,m≤10m \le 10m≤10
对于 70%70\%70% 的数据:$n \le 10^3 ,,, m \le 10^4$
对于 100%100\%100% 的数据:$ n \le 10^5,,, m \le 10^5$

除样例外,p=571373p = 571373p=571373

(数据已经过加强_

样例说明:

故输出应为 171717、222( 40mod38=240 \bmod 38 = 240mod38=2 )

对于这道题,我们首先能确认懒标记应该要有两个,因为对于add而言,懒标记的初始值应该为0,而对于mul而言,懒标记的初始值应该为1,两者肯定不可能是同一个懒标记。
但是对于懒标记mul,初始化起来比较复杂,因此最好的方式就是就是在建树的时候初始化为1,这时候构造结构体的必要性就有了。
下放需要有个规则,首先,下放的时候对于add而言,应该乘以父亲结点的mul,再加上父亲结点的add;对于mul而言,直接乘以父亲结点的mul即可;对于val而言,其等于自己原本的val父亲的mul再加上线段长度父亲的add,说起来有点绕,具体看代码即可

#include
#define ll long long
using namespace std;
const int N=1e5+5;
int n,m,p,a[N];
struct node{ll val,add,mul;int len;
}t[4*N];
inline void buildtree(int k,int l,int r){t[k].add=0,t[k].mul=1;t[k].len=(r-l+1);if(l==r){t[k].val=a[l];return;}int mid=(l+r)>>1;buildtree(k<<1,l,mid),buildtree(k<<1|1,mid+1,r);t[k].val=(t[k<<1].val+t[k<<1|1].val)%p;
}
inline void push_down(int k){t[k<<1].add=(t[k<<1].add*t[k].mul+t[k].add)%p;t[k<<1].mul=(t[k<<1].mul*t[k].mul)%p;t[k<<1].val=t[k<<1].val*t[k].mul%p+t[k<<1].len*t[k].add%p;t[k<<1|1].add=(t[k<<1|1].add*t[k].mul+t[k].add)%p;t[k<<1|1].mul=t[k<<1|1].mul*t[k].mul%p;t[k<<1|1].val=t[k<<1|1].val*t[k].mul%p+t[k<<1|1].len*t[k].add%p;t[k].mul=1,t[k].add=0;
}
inline void push_up(int k){t[k].val=(t[k<<1].val+t[k<<1|1].val)%p;
}
inline void modify(int k,int l,int r,int x,int y,int add,int mul){if(l==x&&y==r){t[k].val=(t[k].val*mul%p+t[k].len*add)%p;t[k].mul=t[k].mul*mul%p;t[k].add=(t[k].add*mul%p+add)%p;return;}if(t[k].add!=0||t[k].mul!=1)push_down(k);int mid=(l+r)>>1;if(y<=mid)modify(k<<1,l,mid,x,y,add,mul);elseif(x>mid)modify(k<<1|1,mid+1,r,x,y,add,mul);else modify(k<<1,l,mid,x,mid,add,mul),modify(k<<1|1,mid+1,r,mid+1,y,add,mul);push_up(k);
}
inline ll query(int k,int l,int r,int x,int y){if(l==x&&r==y)return t[k].val;if(t[k].add!=0||t[k].mul!=1)push_down(k);int mid=(l+r)>>1;ll res;if(y<=mid)res=query(k<<1,l,mid,x,y);elseif(x>mid)res=query(k<<1|1,mid+1,r,x,y);else res=(query(k<<1,l,mid,x,mid)+query(k<<1|1,mid+1,r,mid+1,y))%p;return res;
}
int main(){cin>>n>>m>>p;for(int i=1;i<=n;++i)scanf("%d",&a[i]);buildtree(1,1,n);while(m--){int c,x,y,k;scanf("%d%d%d",&c,&x,&y);if(c==1){scanf("%d",&k);modify(1,1,n,x,y,0,k);}else if(c==2){scanf("%d",&k);modify(1,1,n,x,y,k,1);}else printf("%lld\n",query(1,1,n,x,y));}
}

上一篇:K8S---Helm

下一篇:Django web开发(一) - 前端

相关内容

热门资讯

育碧GDC2018程序化大世界... 1.传统手动绘制森林的问题 采用手动绘制的方法的话,每次迭代地形都要手动再绘制森林。这...
编译原理陈火旺版第三章课后题答... 下面答案仅供参考! 1.编写一个对于 Pascal 源程序的预处理程序。该程序的作用是...
MacBookPro M2芯片... MacBookPro M2芯片下如何搭建React-Native环境目录软件下载环境配置 目录 写在...
Android studio ... 解决 Android studio 出现“The emulator process for AVD ...
pyflink学习笔记(六):... 在pyflink学习笔记(一)中简单介绍了table-sql的窗口函数,下面简单介绍下...
创建deployment 创建deployment服务编排-DeploymentDeployment工作负载均衡器介绍Depl...
gma 1.1.4 (2023... 新增   1、地图工具    a. 增加【GetWorldDEMDataSet】。提供了一套 GEO...
AI专业教您保姆级在暗影精灵8... 目录 一、Stable Diffusion介绍    二、Stable Diffusion环境搭建 ...
vue笔记 第一个Vue应用 Document{{content}}{{...
Unity自带类 --- Ti... 1.在Unity中,自己写的类(脚本)的名字不能与Unit...
托福口语21天——day5 发... 目录 一、连读纠音 二、语料输入+造句输出 三、真题 一、连读纠音 英语中的连读方式有好几种...
五、排序与分页 一、排序 1、语法 ORDER BY 字段 ASC | DESC ASC(ascen...
Linux系统中如何安装软件 文章目录一、rpm包安装方式步骤:二、deb包安装方式步骤:三、tar....
开荒手册4——Related ... 0 写在前面 最早读文献的时候,每每看到related work部分都会选择性的忽略&...
实验01:吃鸡蛋问题 1.实验目的: 通过实验理解算法的概念、算法的表示、算法的时间复杂度和空间复杂度分析&...
8个免费图片/照片压缩工具帮您... 继续查看一些最好的图像压缩工具,以提升用户体验和存储空间以及网站使用支持。 无数图像压...
Spring Cloud Al... 前言 本文小新为大家带来 Sentinel控制台规则配置 相关知识,具体内容包括流控...
多项目同时进行,如何做好进度管... 多项目同时进行,如何做好进度管理? 大多数时候,面对项目进...
ATTCK红队评估实战靶场(二... 前言 第二个靶机来喽,地址:vulunstack 环境配置 大喊一声我...
【MySQL基础】3—多表查询 ⭐⭐⭐⭐⭐⭐ Github主页👉https://github.com/A-BigTr...